cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

omap_vout.c (44356B)


      1/*
      2 * omap_vout.c
      3 *
      4 * Copyright (C) 2005-2010 Texas Instruments.
      5 *
      6 * This file is licensed under the terms of the GNU General Public License
      7 * version 2. This program is licensed "as is" without any warranty of any
      8 * kind, whether express or implied.
      9 *
     10 * Leveraged code from the OMAP2 camera driver
     11 * Video-for-Linux (Version 2) camera capture driver for
     12 * the OMAP24xx camera controller.
     13 *
     14 * Author: Andy Lowe (source@mvista.com)
     15 *
     16 * Copyright (C) 2004 MontaVista Software, Inc.
     17 * Copyright (C) 2010 Texas Instruments.
     18 *
     19 * History:
     20 * 20-APR-2006 Khasim		Modified VRFB based Rotation,
     21 *				The image data is always read from 0 degree
     22 *				view and written
     23 *				to the virtual space of desired rotation angle
     24 * 4-DEC-2006  Jian		Changed to support better memory management
     25 *
     26 * 17-Nov-2008 Hardik		Changed driver to use video_ioctl2
     27 *
     28 * 23-Feb-2010 Vaibhav H	Modified to use new DSS2 interface
     29 *
     30 */
     31
     32#include <linux/init.h>
     33#include <linux/module.h>
     34#include <linux/vmalloc.h>
     35#include <linux/sched.h>
     36#include <linux/types.h>
     37#include <linux/platform_device.h>
     38#include <linux/irq.h>
     39#include <linux/videodev2.h>
     40#include <linux/dma-mapping.h>
     41#include <linux/slab.h>
     42
     43#include <media/v4l2-device.h>
     44#include <media/v4l2-ioctl.h>
     45#include <media/v4l2-event.h>
     46
     47#include <video/omapvrfb.h>
     48#include <video/omapfb_dss.h>
     49
     50#include "omap_voutlib.h"
     51#include "omap_voutdef.h"
     52#include "omap_vout_vrfb.h"
     53
     54MODULE_AUTHOR("Texas Instruments");
     55MODULE_DESCRIPTION("OMAP Video for Linux Video out driver");
     56MODULE_LICENSE("GPL");
     57
     58/* Driver Configuration macros */
     59#define VOUT_NAME		"omap_vout"
     60
     61enum omap_vout_channels {
     62	OMAP_VIDEO1,
     63	OMAP_VIDEO2,
     64};
     65
     66/* Variables configurable through module params*/
     67static bool vid1_static_vrfb_alloc;
     68static bool vid2_static_vrfb_alloc;
     69static bool debug;
     70
     71/* Module parameters */
     72module_param(vid1_static_vrfb_alloc, bool, S_IRUGO);
     73MODULE_PARM_DESC(vid1_static_vrfb_alloc,
     74	"Static allocation of the VRFB buffer for video1 device");
     75
     76module_param(vid2_static_vrfb_alloc, bool, S_IRUGO);
     77MODULE_PARM_DESC(vid2_static_vrfb_alloc,
     78	"Static allocation of the VRFB buffer for video2 device");
     79
     80module_param(debug, bool, S_IRUGO);
     81MODULE_PARM_DESC(debug, "Debug level (0-1)");
     82
     83/* list of image formats supported by OMAP2 video pipelines */
     84static const struct v4l2_fmtdesc omap_formats[] = {
     85	{
     86		/* Note:  V4L2 defines RGB565 as:
     87		 *
     88		 *      Byte 0                    Byte 1
     89		 *      g2 g1 g0 r4 r3 r2 r1 r0   b4 b3 b2 b1 b0 g5 g4 g3
     90		 *
     91		 * We interpret RGB565 as:
     92		 *
     93		 *      Byte 0                    Byte 1
     94		 *      g2 g1 g0 b4 b3 b2 b1 b0   r4 r3 r2 r1 r0 g5 g4 g3
     95		 */
     96		.pixelformat = V4L2_PIX_FMT_RGB565,
     97	},
     98	{
     99		/* Note:  V4L2 defines RGB32 as: RGB-8-8-8-8  we use
    100		 *  this for RGB24 unpack mode, the last 8 bits are ignored
    101		 * */
    102		.pixelformat = V4L2_PIX_FMT_RGB32,
    103	},
    104	{
    105		/* Note:  V4L2 defines RGB24 as: RGB-8-8-8  we use
    106		 *        this for RGB24 packed mode
    107		 *
    108		 */
    109		.pixelformat = V4L2_PIX_FMT_RGB24,
    110	},
    111	{
    112		.pixelformat = V4L2_PIX_FMT_YUYV,
    113	},
    114	{
    115		.pixelformat = V4L2_PIX_FMT_UYVY,
    116	},
    117};
    118
    119#define NUM_OUTPUT_FORMATS (ARRAY_SIZE(omap_formats))
    120
    121/*
    122 * Try format
    123 */
    124static int omap_vout_try_format(struct v4l2_pix_format *pix)
    125{
    126	int ifmt, bpp = 0;
    127
    128	pix->height = clamp(pix->height, (u32)VID_MIN_HEIGHT,
    129						(u32)VID_MAX_HEIGHT);
    130	pix->width = clamp(pix->width, (u32)VID_MIN_WIDTH, (u32)VID_MAX_WIDTH);
    131
    132	for (ifmt = 0; ifmt < NUM_OUTPUT_FORMATS; ifmt++) {
    133		if (pix->pixelformat == omap_formats[ifmt].pixelformat)
    134			break;
    135	}
    136
    137	if (ifmt == NUM_OUTPUT_FORMATS)
    138		ifmt = 0;
    139
    140	pix->pixelformat = omap_formats[ifmt].pixelformat;
    141	pix->field = V4L2_FIELD_NONE;
    142
    143	switch (pix->pixelformat) {
    144	case V4L2_PIX_FMT_YUYV:
    145	case V4L2_PIX_FMT_UYVY:
    146	default:
    147		pix->colorspace = V4L2_COLORSPACE_SRGB;
    148		bpp = YUYV_BPP;
    149		break;
    150	case V4L2_PIX_FMT_RGB565:
    151	case V4L2_PIX_FMT_RGB565X:
    152		pix->colorspace = V4L2_COLORSPACE_SRGB;
    153		bpp = RGB565_BPP;
    154		break;
    155	case V4L2_PIX_FMT_RGB24:
    156		pix->colorspace = V4L2_COLORSPACE_SRGB;
    157		bpp = RGB24_BPP;
    158		break;
    159	case V4L2_PIX_FMT_RGB32:
    160	case V4L2_PIX_FMT_BGR32:
    161		pix->colorspace = V4L2_COLORSPACE_SRGB;
    162		bpp = RGB32_BPP;
    163		break;
    164	}
    165	pix->bytesperline = pix->width * bpp;
    166	pix->sizeimage = pix->bytesperline * pix->height;
    167
    168	return bpp;
    169}
    170
    171/*
    172 * Convert V4L2 rotation to DSS rotation
    173 *	V4L2 understand 0, 90, 180, 270.
    174 *	Convert to 0, 1, 2 and 3 respectively for DSS
    175 */
    176static int v4l2_rot_to_dss_rot(int v4l2_rotation,
    177			enum dss_rotation *rotation, bool mirror)
    178{
    179	int ret = 0;
    180
    181	switch (v4l2_rotation) {
    182	case 90:
    183		*rotation = dss_rotation_90_degree;
    184		break;
    185	case 180:
    186		*rotation = dss_rotation_180_degree;
    187		break;
    188	case 270:
    189		*rotation = dss_rotation_270_degree;
    190		break;
    191	case 0:
    192		*rotation = dss_rotation_0_degree;
    193		break;
    194	default:
    195		ret = -EINVAL;
    196	}
    197	return ret;
    198}
    199
    200static int omap_vout_calculate_offset(struct omap_vout_device *vout)
    201{
    202	struct omapvideo_info *ovid;
    203	struct v4l2_rect *crop = &vout->crop;
    204	struct v4l2_pix_format *pix = &vout->pix;
    205	int *cropped_offset = &vout->cropped_offset;
    206	int ps = 2, line_length = 0;
    207
    208	ovid = &vout->vid_info;
    209
    210	if (ovid->rotation_type == VOUT_ROT_VRFB) {
    211		omap_vout_calculate_vrfb_offset(vout);
    212	} else {
    213		vout->line_length = line_length = pix->width;
    214
    215		if (V4L2_PIX_FMT_YUYV == pix->pixelformat ||
    216			V4L2_PIX_FMT_UYVY == pix->pixelformat)
    217			ps = 2;
    218		else if (V4L2_PIX_FMT_RGB32 == pix->pixelformat)
    219			ps = 4;
    220		else if (V4L2_PIX_FMT_RGB24 == pix->pixelformat)
    221			ps = 3;
    222
    223		vout->ps = ps;
    224
    225		*cropped_offset = (line_length * ps) *
    226			crop->top + crop->left * ps;
    227	}
    228
    229	v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev, "%s Offset:%x\n",
    230			__func__, vout->cropped_offset);
    231
    232	return 0;
    233}
    234
    235/*
    236 * Convert V4L2 pixel format to DSS pixel format
    237 */
    238static int video_mode_to_dss_mode(struct omap_vout_device *vout)
    239{
    240	struct omap_overlay *ovl;
    241	struct omapvideo_info *ovid;
    242	struct v4l2_pix_format *pix = &vout->pix;
    243	enum omap_color_mode mode;
    244
    245	ovid = &vout->vid_info;
    246	ovl = ovid->overlays[0];
    247
    248	switch (pix->pixelformat) {
    249	case V4L2_PIX_FMT_YUYV:
    250		mode = OMAP_DSS_COLOR_YUV2;
    251		break;
    252	case V4L2_PIX_FMT_UYVY:
    253		mode = OMAP_DSS_COLOR_UYVY;
    254		break;
    255	case V4L2_PIX_FMT_RGB565:
    256		mode = OMAP_DSS_COLOR_RGB16;
    257		break;
    258	case V4L2_PIX_FMT_RGB24:
    259		mode = OMAP_DSS_COLOR_RGB24P;
    260		break;
    261	case V4L2_PIX_FMT_RGB32:
    262		mode = (ovl->id == OMAP_DSS_VIDEO1) ?
    263			OMAP_DSS_COLOR_RGB24U : OMAP_DSS_COLOR_ARGB32;
    264		break;
    265	case V4L2_PIX_FMT_BGR32:
    266		mode = OMAP_DSS_COLOR_RGBX32;
    267		break;
    268	default:
    269		mode = -EINVAL;
    270		break;
    271	}
    272	return mode;
    273}
    274
    275/*
    276 * Setup the overlay
    277 */
    278static int omapvid_setup_overlay(struct omap_vout_device *vout,
    279		struct omap_overlay *ovl, int posx, int posy, int outw,
    280		int outh, dma_addr_t addr)
    281{
    282	int ret = 0;
    283	struct omap_overlay_info info;
    284	int cropheight, cropwidth, pixwidth;
    285
    286	if ((ovl->caps & OMAP_DSS_OVL_CAP_SCALE) == 0 &&
    287			(outw != vout->pix.width || outh != vout->pix.height)) {
    288		ret = -EINVAL;
    289		goto setup_ovl_err;
    290	}
    291
    292	vout->dss_mode = video_mode_to_dss_mode(vout);
    293	if (vout->dss_mode == -EINVAL) {
    294		ret = -EINVAL;
    295		goto setup_ovl_err;
    296	}
    297
    298	/* Setup the input plane parameters according to
    299	 * rotation value selected.
    300	 */
    301	if (is_rotation_90_or_270(vout)) {
    302		cropheight = vout->crop.width;
    303		cropwidth = vout->crop.height;
    304		pixwidth = vout->pix.height;
    305	} else {
    306		cropheight = vout->crop.height;
    307		cropwidth = vout->crop.width;
    308		pixwidth = vout->pix.width;
    309	}
    310
    311	ovl->get_overlay_info(ovl, &info);
    312	info.paddr = addr;
    313	info.width = cropwidth;
    314	info.height = cropheight;
    315	info.color_mode = vout->dss_mode;
    316	info.mirror = vout->mirror;
    317	info.pos_x = posx;
    318	info.pos_y = posy;
    319	info.out_width = outw;
    320	info.out_height = outh;
    321	info.global_alpha = vout->win.global_alpha;
    322	if (!is_rotation_enabled(vout)) {
    323		info.rotation = 0;
    324		info.rotation_type = OMAP_DSS_ROT_DMA;
    325		info.screen_width = pixwidth;
    326	} else {
    327		info.rotation = vout->rotation;
    328		info.rotation_type = OMAP_DSS_ROT_VRFB;
    329		info.screen_width = 2048;
    330	}
    331
    332	v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
    333		"%s enable=%d addr=%pad width=%d\n height=%d color_mode=%d\n"
    334		"rotation=%d mirror=%d posx=%d posy=%d out_width = %d \n"
    335		"out_height=%d rotation_type=%d screen_width=%d\n", __func__,
    336		ovl->is_enabled(ovl), &info.paddr, info.width, info.height,
    337		info.color_mode, info.rotation, info.mirror, info.pos_x,
    338		info.pos_y, info.out_width, info.out_height, info.rotation_type,
    339		info.screen_width);
    340
    341	ret = ovl->set_overlay_info(ovl, &info);
    342	if (ret)
    343		goto setup_ovl_err;
    344
    345	return 0;
    346
    347setup_ovl_err:
    348	v4l2_warn(&vout->vid_dev->v4l2_dev, "setup_overlay failed\n");
    349	return ret;
    350}
    351
    352/*
    353 * Initialize the overlay structure
    354 */
    355static int omapvid_init(struct omap_vout_device *vout, dma_addr_t addr)
    356{
    357	int ret = 0, i;
    358	struct v4l2_window *win;
    359	struct omap_overlay *ovl;
    360	int posx, posy, outw, outh;
    361	struct omap_video_timings *timing;
    362	struct omapvideo_info *ovid = &vout->vid_info;
    363
    364	win = &vout->win;
    365	for (i = 0; i < ovid->num_overlays; i++) {
    366		struct omap_dss_device *dssdev;
    367
    368		ovl = ovid->overlays[i];
    369		dssdev = ovl->get_device(ovl);
    370
    371		if (!dssdev)
    372			return -EINVAL;
    373
    374		timing = &dssdev->panel.timings;
    375
    376		outw = win->w.width;
    377		outh = win->w.height;
    378		switch (vout->rotation) {
    379		case dss_rotation_90_degree:
    380			/* Invert the height and width for 90
    381			 * and 270 degree rotation
    382			 */
    383			swap(outw, outh);
    384			posy = (timing->y_res - win->w.width) - win->w.left;
    385			posx = win->w.top;
    386			break;
    387
    388		case dss_rotation_180_degree:
    389			posx = (timing->x_res - win->w.width) - win->w.left;
    390			posy = (timing->y_res - win->w.height) - win->w.top;
    391			break;
    392
    393		case dss_rotation_270_degree:
    394			swap(outw, outh);
    395			posy = win->w.left;
    396			posx = (timing->x_res - win->w.height) - win->w.top;
    397			break;
    398
    399		default:
    400			posx = win->w.left;
    401			posy = win->w.top;
    402			break;
    403		}
    404
    405		ret = omapvid_setup_overlay(vout, ovl, posx, posy,
    406				outw, outh, addr);
    407		if (ret)
    408			goto omapvid_init_err;
    409	}
    410	return 0;
    411
    412omapvid_init_err:
    413	v4l2_warn(&vout->vid_dev->v4l2_dev, "apply_changes failed\n");
    414	return ret;
    415}
    416
    417/*
    418 * Apply the changes set the go bit of DSS
    419 */
    420static int omapvid_apply_changes(struct omap_vout_device *vout)
    421{
    422	int i;
    423	struct omap_overlay *ovl;
    424	struct omapvideo_info *ovid = &vout->vid_info;
    425
    426	for (i = 0; i < ovid->num_overlays; i++) {
    427		struct omap_dss_device *dssdev;
    428
    429		ovl = ovid->overlays[i];
    430		dssdev = ovl->get_device(ovl);
    431		if (!dssdev)
    432			return -EINVAL;
    433		ovl->manager->apply(ovl->manager);
    434	}
    435
    436	return 0;
    437}
    438
    439static int omapvid_handle_interlace_display(struct omap_vout_device *vout,
    440		unsigned int irqstatus, u64 ts)
    441{
    442	u32 fid;
    443
    444	if (vout->first_int) {
    445		vout->first_int = 0;
    446		goto err;
    447	}
    448
    449	if (irqstatus & DISPC_IRQ_EVSYNC_ODD)
    450		fid = 1;
    451	else if (irqstatus & DISPC_IRQ_EVSYNC_EVEN)
    452		fid = 0;
    453	else
    454		goto err;
    455
    456	vout->field_id ^= 1;
    457	if (fid != vout->field_id) {
    458		if (fid == 0)
    459			vout->field_id = fid;
    460	} else if (0 == fid) {
    461		if (vout->cur_frm == vout->next_frm)
    462			goto err;
    463
    464		vout->cur_frm->vbuf.vb2_buf.timestamp = ts;
    465		vout->cur_frm->vbuf.sequence = vout->sequence++;
    466		vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_DONE);
    467		vout->cur_frm = vout->next_frm;
    468	} else {
    469		if (list_empty(&vout->dma_queue) ||
    470				(vout->cur_frm != vout->next_frm))
    471			goto err;
    472	}
    473
    474	return vout->field_id;
    475err:
    476	return 0;
    477}
    478
    479static void omap_vout_isr(void *arg, unsigned int irqstatus)
    480{
    481	int ret, fid, mgr_id;
    482	dma_addr_t addr;
    483	u32 irq;
    484	struct omap_overlay *ovl;
    485	u64 ts;
    486	struct omapvideo_info *ovid;
    487	struct omap_dss_device *cur_display;
    488	struct omap_vout_device *vout = (struct omap_vout_device *)arg;
    489
    490	ovid = &vout->vid_info;
    491	ovl = ovid->overlays[0];
    492
    493	mgr_id = ovl->manager->id;
    494
    495	/* get the display device attached to the overlay */
    496	cur_display = ovl->get_device(ovl);
    497
    498	if (!cur_display)
    499		return;
    500
    501	spin_lock(&vout->vbq_lock);
    502	ts = ktime_get_ns();
    503
    504	switch (cur_display->type) {
    505	case OMAP_DISPLAY_TYPE_DSI:
    506	case OMAP_DISPLAY_TYPE_DPI:
    507	case OMAP_DISPLAY_TYPE_DVI:
    508		if (mgr_id == OMAP_DSS_CHANNEL_LCD)
    509			irq = DISPC_IRQ_VSYNC;
    510		else if (mgr_id == OMAP_DSS_CHANNEL_LCD2)
    511			irq = DISPC_IRQ_VSYNC2;
    512		else
    513			goto vout_isr_err;
    514
    515		if (!(irqstatus & irq))
    516			goto vout_isr_err;
    517		break;
    518	case OMAP_DISPLAY_TYPE_VENC:
    519		fid = omapvid_handle_interlace_display(vout, irqstatus,
    520				ts);
    521		if (!fid)
    522			goto vout_isr_err;
    523		break;
    524	case OMAP_DISPLAY_TYPE_HDMI:
    525		if (!(irqstatus & DISPC_IRQ_EVSYNC_EVEN))
    526			goto vout_isr_err;
    527		break;
    528	default:
    529		goto vout_isr_err;
    530	}
    531
    532	if (!vout->first_int && (vout->cur_frm != vout->next_frm)) {
    533		vout->cur_frm->vbuf.vb2_buf.timestamp = ts;
    534		vout->cur_frm->vbuf.sequence = vout->sequence++;
    535		vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_DONE);
    536		vout->cur_frm = vout->next_frm;
    537	}
    538
    539	vout->first_int = 0;
    540	if (list_empty(&vout->dma_queue))
    541		goto vout_isr_err;
    542
    543	vout->next_frm = list_entry(vout->dma_queue.next,
    544			struct omap_vout_buffer, queue);
    545	list_del(&vout->next_frm->queue);
    546
    547	addr = vout->queued_buf_addr[vout->next_frm->vbuf.vb2_buf.index]
    548		+ vout->cropped_offset;
    549
    550	/* First save the configuration in ovelray structure */
    551	ret = omapvid_init(vout, addr);
    552	if (ret) {
    553		printk(KERN_ERR VOUT_NAME
    554			"failed to set overlay info\n");
    555		goto vout_isr_err;
    556	}
    557
    558	/* Enable the pipeline and set the Go bit */
    559	ret = omapvid_apply_changes(vout);
    560	if (ret)
    561		printk(KERN_ERR VOUT_NAME "failed to change mode\n");
    562
    563vout_isr_err:
    564	spin_unlock(&vout->vbq_lock);
    565}
    566
    567
    568/*
    569 * V4L2 ioctls
    570 */
    571static int vidioc_querycap(struct file *file, void *fh,
    572		struct v4l2_capability *cap)
    573{
    574	struct omap_vout_device *vout = video_drvdata(file);
    575
    576	strscpy(cap->driver, VOUT_NAME, sizeof(cap->driver));
    577	strscpy(cap->card, vout->vfd->name, sizeof(cap->card));
    578	snprintf(cap->bus_info, sizeof(cap->bus_info),
    579		 "platform:%s.%d", VOUT_NAME, vout->vid);
    580	return 0;
    581}
    582
    583static int vidioc_enum_fmt_vid_out(struct file *file, void *fh,
    584			struct v4l2_fmtdesc *fmt)
    585{
    586	int index = fmt->index;
    587
    588	if (index >= NUM_OUTPUT_FORMATS)
    589		return -EINVAL;
    590
    591	fmt->flags = omap_formats[index].flags;
    592	fmt->pixelformat = omap_formats[index].pixelformat;
    593
    594	return 0;
    595}
    596
    597static int vidioc_g_fmt_vid_out(struct file *file, void *fh,
    598			struct v4l2_format *f)
    599{
    600	struct omap_vout_device *vout = video_drvdata(file);
    601
    602	f->fmt.pix = vout->pix;
    603	return 0;
    604
    605}
    606
    607static int vidioc_try_fmt_vid_out(struct file *file, void *fh,
    608			struct v4l2_format *f)
    609{
    610	struct omap_overlay *ovl;
    611	struct omapvideo_info *ovid;
    612	struct omap_video_timings *timing;
    613	struct omap_vout_device *vout = video_drvdata(file);
    614	struct omap_dss_device *dssdev;
    615
    616	ovid = &vout->vid_info;
    617	ovl = ovid->overlays[0];
    618	/* get the display device attached to the overlay */
    619	dssdev = ovl->get_device(ovl);
    620
    621	if (!dssdev)
    622		return -EINVAL;
    623
    624	timing = &dssdev->panel.timings;
    625
    626	vout->fbuf.fmt.height = timing->y_res;
    627	vout->fbuf.fmt.width = timing->x_res;
    628
    629	omap_vout_try_format(&f->fmt.pix);
    630	return 0;
    631}
    632
    633static int vidioc_s_fmt_vid_out(struct file *file, void *fh,
    634			struct v4l2_format *f)
    635{
    636	int ret, bpp;
    637	struct omap_overlay *ovl;
    638	struct omapvideo_info *ovid;
    639	struct omap_video_timings *timing;
    640	struct omap_vout_device *vout = video_drvdata(file);
    641	struct omap_dss_device *dssdev;
    642
    643	if (vb2_is_busy(&vout->vq))
    644		return -EBUSY;
    645
    646	ovid = &vout->vid_info;
    647	ovl = ovid->overlays[0];
    648	dssdev = ovl->get_device(ovl);
    649
    650	/* get the display device attached to the overlay */
    651	if (!dssdev) {
    652		ret = -EINVAL;
    653		goto s_fmt_vid_out_exit;
    654	}
    655	timing = &dssdev->panel.timings;
    656
    657	/* We don't support RGB24-packed mode if vrfb rotation
    658	 * is enabled*/
    659	if ((is_rotation_enabled(vout)) &&
    660			f->fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) {
    661		ret = -EINVAL;
    662		goto s_fmt_vid_out_exit;
    663	}
    664
    665	/* get the framebuffer parameters */
    666
    667	if (is_rotation_90_or_270(vout)) {
    668		vout->fbuf.fmt.height = timing->x_res;
    669		vout->fbuf.fmt.width = timing->y_res;
    670	} else {
    671		vout->fbuf.fmt.height = timing->y_res;
    672		vout->fbuf.fmt.width = timing->x_res;
    673	}
    674
    675	/* change to smaller size is OK */
    676
    677	bpp = omap_vout_try_format(&f->fmt.pix);
    678	f->fmt.pix.sizeimage = f->fmt.pix.width * f->fmt.pix.height * bpp;
    679
    680	/* try & set the new output format */
    681	vout->bpp = bpp;
    682	vout->pix = f->fmt.pix;
    683	vout->vrfb_bpp = 1;
    684
    685	/* If YUYV then vrfb bpp is 2, for  others its 1 */
    686	if (V4L2_PIX_FMT_YUYV == vout->pix.pixelformat ||
    687			V4L2_PIX_FMT_UYVY == vout->pix.pixelformat)
    688		vout->vrfb_bpp = 2;
    689
    690	/* set default crop and win */
    691	omap_vout_new_format(&vout->pix, &vout->fbuf, &vout->crop, &vout->win);
    692
    693	ret = 0;
    694
    695s_fmt_vid_out_exit:
    696	return ret;
    697}
    698
    699static int vidioc_try_fmt_vid_overlay(struct file *file, void *fh,
    700			struct v4l2_format *f)
    701{
    702	int ret = 0;
    703	struct omap_vout_device *vout = video_drvdata(file);
    704	struct omap_overlay *ovl;
    705	struct omapvideo_info *ovid;
    706	struct v4l2_window *win = &f->fmt.win;
    707
    708	ovid = &vout->vid_info;
    709	ovl = ovid->overlays[0];
    710
    711	ret = omap_vout_try_window(&vout->fbuf, win);
    712
    713	if (!ret && !(ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA))
    714		win->global_alpha = 0;
    715
    716	return ret;
    717}
    718
    719static int vidioc_s_fmt_vid_overlay(struct file *file, void *fh,
    720			struct v4l2_format *f)
    721{
    722	int ret = 0;
    723	struct omap_overlay *ovl;
    724	struct omapvideo_info *ovid;
    725	struct omap_vout_device *vout = video_drvdata(file);
    726	struct v4l2_window *win = &f->fmt.win;
    727
    728	ovid = &vout->vid_info;
    729	ovl = ovid->overlays[0];
    730
    731	ret = omap_vout_new_window(&vout->crop, &vout->win, &vout->fbuf, win);
    732	if (!ret) {
    733		enum omap_dss_trans_key_type key_type =
    734			OMAP_DSS_COLOR_KEY_GFX_DST;
    735		int enable;
    736
    737		/* Video1 plane does not support global alpha on OMAP3 */
    738		if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA)
    739			vout->win.global_alpha = win->global_alpha;
    740		else
    741			win->global_alpha = 0;
    742		if (vout->fbuf.flags & (V4L2_FBUF_FLAG_CHROMAKEY |
    743					V4L2_FBUF_FLAG_SRC_CHROMAKEY))
    744			enable = 1;
    745		else
    746			enable = 0;
    747		if (vout->fbuf.flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY)
    748			key_type = OMAP_DSS_COLOR_KEY_VID_SRC;
    749
    750		if (ovl->manager && ovl->manager->get_manager_info &&
    751		    ovl->manager->set_manager_info) {
    752			struct omap_overlay_manager_info info;
    753
    754			ovl->manager->get_manager_info(ovl->manager, &info);
    755			info.trans_enabled = enable;
    756			info.trans_key_type = key_type;
    757			info.trans_key = vout->win.chromakey;
    758
    759			if (ovl->manager->set_manager_info(ovl->manager, &info))
    760				return -EINVAL;
    761		}
    762	}
    763	return ret;
    764}
    765
    766static int vidioc_g_fmt_vid_overlay(struct file *file, void *fh,
    767			struct v4l2_format *f)
    768{
    769	struct omap_overlay *ovl;
    770	struct omapvideo_info *ovid;
    771	struct omap_vout_device *vout = video_drvdata(file);
    772	struct v4l2_window *win = &f->fmt.win;
    773
    774	ovid = &vout->vid_info;
    775	ovl = ovid->overlays[0];
    776
    777	win->w = vout->win.w;
    778	win->field = vout->win.field;
    779	win->chromakey = vout->win.chromakey;
    780	if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA)
    781		win->global_alpha = vout->win.global_alpha;
    782	else
    783		win->global_alpha = 0;
    784	win->clips = NULL;
    785	win->clipcount = 0;
    786	win->bitmap = NULL;
    787	return 0;
    788}
    789
    790static int vidioc_g_selection(struct file *file, void *fh, struct v4l2_selection *sel)
    791{
    792	struct omap_vout_device *vout = video_drvdata(file);
    793	struct v4l2_pix_format *pix = &vout->pix;
    794
    795	if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
    796		return -EINVAL;
    797
    798	switch (sel->target) {
    799	case V4L2_SEL_TGT_CROP:
    800		sel->r = vout->crop;
    801		break;
    802	case V4L2_SEL_TGT_CROP_DEFAULT:
    803		omap_vout_default_crop(&vout->pix, &vout->fbuf, &sel->r);
    804		break;
    805	case V4L2_SEL_TGT_CROP_BOUNDS:
    806		/* Width and height are always even */
    807		sel->r.width = pix->width & ~1;
    808		sel->r.height = pix->height & ~1;
    809		break;
    810	default:
    811		return -EINVAL;
    812	}
    813	return 0;
    814}
    815
    816static int vidioc_s_selection(struct file *file, void *fh, struct v4l2_selection *sel)
    817{
    818	int ret = -EINVAL;
    819	struct omap_vout_device *vout = video_drvdata(file);
    820	struct omapvideo_info *ovid;
    821	struct omap_overlay *ovl;
    822	struct omap_video_timings *timing;
    823	struct omap_dss_device *dssdev;
    824
    825	if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
    826		return -EINVAL;
    827
    828	if (sel->target != V4L2_SEL_TGT_CROP)
    829		return -EINVAL;
    830
    831	if (vb2_is_busy(&vout->vq))
    832		return -EBUSY;
    833
    834	ovid = &vout->vid_info;
    835	ovl = ovid->overlays[0];
    836	/* get the display device attached to the overlay */
    837	dssdev = ovl->get_device(ovl);
    838
    839	if (!dssdev) {
    840		ret = -EINVAL;
    841		goto s_crop_err;
    842	}
    843
    844	timing = &dssdev->panel.timings;
    845
    846	if (is_rotation_90_or_270(vout)) {
    847		vout->fbuf.fmt.height = timing->x_res;
    848		vout->fbuf.fmt.width = timing->y_res;
    849	} else {
    850		vout->fbuf.fmt.height = timing->y_res;
    851		vout->fbuf.fmt.width = timing->x_res;
    852	}
    853
    854	ret = omap_vout_new_crop(&vout->pix, &vout->crop, &vout->win,
    855				 &vout->fbuf, &sel->r);
    856
    857s_crop_err:
    858	return ret;
    859}
    860
    861static int omap_vout_s_ctrl(struct v4l2_ctrl *ctrl)
    862{
    863	struct omap_vout_device *vout =
    864		container_of(ctrl->handler, struct omap_vout_device, ctrl_handler);
    865	int ret = 0;
    866
    867	switch (ctrl->id) {
    868	case V4L2_CID_ROTATE: {
    869		struct omapvideo_info *ovid;
    870		int rotation = ctrl->val;
    871
    872		ovid = &vout->vid_info;
    873
    874		if (rotation && ovid->rotation_type == VOUT_ROT_NONE) {
    875			ret = -ERANGE;
    876			break;
    877		}
    878
    879		if (rotation && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
    880			ret = -EINVAL;
    881			break;
    882		}
    883
    884		if (v4l2_rot_to_dss_rot(rotation, &vout->rotation,
    885							vout->mirror)) {
    886			ret = -EINVAL;
    887			break;
    888		}
    889		break;
    890	}
    891	case V4L2_CID_BG_COLOR:
    892	{
    893		struct omap_overlay *ovl;
    894		unsigned int color = ctrl->val;
    895		struct omap_overlay_manager_info info;
    896
    897		ovl = vout->vid_info.overlays[0];
    898
    899		if (!ovl->manager || !ovl->manager->get_manager_info) {
    900			ret = -EINVAL;
    901			break;
    902		}
    903
    904		ovl->manager->get_manager_info(ovl->manager, &info);
    905		info.default_color = color;
    906		if (ovl->manager->set_manager_info(ovl->manager, &info)) {
    907			ret = -EINVAL;
    908			break;
    909		}
    910		break;
    911	}
    912	case V4L2_CID_VFLIP:
    913	{
    914		struct omapvideo_info *ovid;
    915		unsigned int mirror = ctrl->val;
    916
    917		ovid = &vout->vid_info;
    918
    919		if (mirror && ovid->rotation_type == VOUT_ROT_NONE) {
    920			ret = -ERANGE;
    921			break;
    922		}
    923
    924		if (mirror  && vout->pix.pixelformat == V4L2_PIX_FMT_RGB24) {
    925			ret = -EINVAL;
    926			break;
    927		}
    928		vout->mirror = mirror;
    929		break;
    930	}
    931	default:
    932		return -EINVAL;
    933	}
    934	return ret;
    935}
    936
    937static const struct v4l2_ctrl_ops omap_vout_ctrl_ops = {
    938	.s_ctrl = omap_vout_s_ctrl,
    939};
    940
    941static int omap_vout_vb2_queue_setup(struct vb2_queue *vq,
    942				     unsigned int *nbufs,
    943				     unsigned int *num_planes, unsigned int sizes[],
    944				     struct device *alloc_devs[])
    945{
    946	struct omap_vout_device *vout = vb2_get_drv_priv(vq);
    947	int size = vout->pix.sizeimage;
    948
    949	if (is_rotation_enabled(vout) && vq->num_buffers + *nbufs > VRFB_NUM_BUFS) {
    950		*nbufs = VRFB_NUM_BUFS - vq->num_buffers;
    951		if (*nbufs == 0)
    952			return -EINVAL;
    953	}
    954
    955	if (*num_planes)
    956		return sizes[0] < size ? -EINVAL : 0;
    957
    958	*num_planes = 1;
    959	sizes[0] = size;
    960	return 0;
    961}
    962
    963static int omap_vout_vb2_prepare(struct vb2_buffer *vb)
    964{
    965	struct omap_vout_device *vout = vb2_get_drv_priv(vb->vb2_queue);
    966	struct omapvideo_info *ovid = &vout->vid_info;
    967	struct omap_vout_buffer *voutbuf = vb2_to_omap_vout_buffer(vb);
    968	dma_addr_t buf_phy_addr = vb2_dma_contig_plane_dma_addr(vb, 0);
    969
    970	if (vb2_plane_size(vb, 0) < vout->pix.sizeimage) {
    971		v4l2_dbg(1, debug, &vout->vid_dev->v4l2_dev,
    972			 "%s data will not fit into plane (%lu < %u)\n",
    973			__func__, vb2_plane_size(vb, 0), vout->pix.sizeimage);
    974		return -EINVAL;
    975	}
    976
    977	vb2_set_plane_payload(vb, 0, vout->pix.sizeimage);
    978	voutbuf->vbuf.field = V4L2_FIELD_NONE;
    979
    980	vout->queued_buf_addr[vb->index] = buf_phy_addr;
    981	if (ovid->rotation_type == VOUT_ROT_VRFB)
    982		return omap_vout_prepare_vrfb(vout, vb);
    983	return 0;
    984}
    985
    986static void omap_vout_vb2_queue(struct vb2_buffer *vb)
    987{
    988	struct omap_vout_device *vout = vb2_get_drv_priv(vb->vb2_queue);
    989	struct omap_vout_buffer *voutbuf = vb2_to_omap_vout_buffer(vb);
    990
    991	list_add_tail(&voutbuf->queue, &vout->dma_queue);
    992}
    993
    994static int omap_vout_vb2_start_streaming(struct vb2_queue *vq, unsigned int count)
    995{
    996	struct omap_vout_device *vout = vb2_get_drv_priv(vq);
    997	struct omapvideo_info *ovid = &vout->vid_info;
    998	struct omap_vout_buffer *buf, *tmp;
    999	dma_addr_t addr = 0;
   1000	u32 mask = 0;
   1001	int ret, j;
   1002
   1003	/* Get the next frame from the buffer queue */
   1004	vout->next_frm = vout->cur_frm = list_entry(vout->dma_queue.next,
   1005			struct omap_vout_buffer, queue);
   1006	/* Remove buffer from the buffer queue */
   1007	list_del(&vout->cur_frm->queue);
   1008	/* Initialize field_id and started member */
   1009	vout->field_id = 0;
   1010	vout->first_int = 1;
   1011	vout->sequence = 0;
   1012
   1013	if (omap_vout_calculate_offset(vout)) {
   1014		ret = -EINVAL;
   1015		goto out;
   1016	}
   1017	if (ovid->rotation_type == VOUT_ROT_VRFB)
   1018		if (omap_vout_vrfb_buffer_setup(vout, &count, 0)) {
   1019			ret = -ENOMEM;
   1020			goto out;
   1021		}
   1022
   1023	addr = vout->queued_buf_addr[vout->cur_frm->vbuf.vb2_buf.index]
   1024		+ vout->cropped_offset;
   1025
   1026	mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
   1027		| DISPC_IRQ_VSYNC2;
   1028
   1029	/* First save the configuration in overlay structure */
   1030	ret = omapvid_init(vout, addr);
   1031	if (ret) {
   1032		v4l2_err(&vout->vid_dev->v4l2_dev,
   1033				"failed to set overlay info\n");
   1034		goto streamon_err1;
   1035	}
   1036
   1037	omap_dispc_register_isr(omap_vout_isr, vout, mask);
   1038
   1039	/* Enable the pipeline and set the Go bit */
   1040	ret = omapvid_apply_changes(vout);
   1041	if (ret)
   1042		v4l2_err(&vout->vid_dev->v4l2_dev, "failed to change mode\n");
   1043
   1044	for (j = 0; j < ovid->num_overlays; j++) {
   1045		struct omap_overlay *ovl = ovid->overlays[j];
   1046		struct omap_dss_device *dssdev = ovl->get_device(ovl);
   1047
   1048		if (dssdev) {
   1049			ret = ovl->enable(ovl);
   1050			if (ret)
   1051				goto streamon_err1;
   1052		}
   1053	}
   1054	return 0;
   1055
   1056streamon_err1:
   1057	mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
   1058		| DISPC_IRQ_VSYNC2;
   1059
   1060	omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
   1061
   1062	for (j = 0; j < ovid->num_overlays; j++) {
   1063		struct omap_overlay *ovl = ovid->overlays[j];
   1064		struct omap_dss_device *dssdev = ovl->get_device(ovl);
   1065
   1066		if (dssdev)
   1067			ovl->disable(ovl);
   1068	}
   1069	/* Turn of the pipeline */
   1070	if (omapvid_apply_changes(vout))
   1071		v4l2_err(&vout->vid_dev->v4l2_dev,
   1072			 "failed to change mode in streamoff\n");
   1073
   1074out:
   1075	vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_QUEUED);
   1076	list_for_each_entry_safe(buf, tmp, &vout->dma_queue, queue) {
   1077		list_del(&buf->queue);
   1078		vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_QUEUED);
   1079	}
   1080	return ret;
   1081}
   1082
   1083static void omap_vout_vb2_stop_streaming(struct vb2_queue *vq)
   1084{
   1085	struct omap_vout_device *vout = vb2_get_drv_priv(vq);
   1086	struct omapvideo_info *ovid = &vout->vid_info;
   1087	struct omap_vout_buffer *buf, *tmp;
   1088	u32 mask = 0;
   1089	int j;
   1090
   1091	mask = DISPC_IRQ_VSYNC | DISPC_IRQ_EVSYNC_EVEN | DISPC_IRQ_EVSYNC_ODD
   1092		| DISPC_IRQ_VSYNC2;
   1093
   1094	omap_dispc_unregister_isr(omap_vout_isr, vout, mask);
   1095
   1096	for (j = 0; j < ovid->num_overlays; j++) {
   1097		struct omap_overlay *ovl = ovid->overlays[j];
   1098		struct omap_dss_device *dssdev = ovl->get_device(ovl);
   1099
   1100		if (dssdev)
   1101			ovl->disable(ovl);
   1102	}
   1103	/* Turn of the pipeline */
   1104	if (omapvid_apply_changes(vout))
   1105		v4l2_err(&vout->vid_dev->v4l2_dev,
   1106			 "failed to change mode in streamoff\n");
   1107
   1108	if (vout->next_frm != vout->cur_frm)
   1109		vb2_buffer_done(&vout->next_frm->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
   1110	vb2_buffer_done(&vout->cur_frm->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
   1111	list_for_each_entry_safe(buf, tmp, &vout->dma_queue, queue) {
   1112		list_del(&buf->queue);
   1113		vb2_buffer_done(&buf->vbuf.vb2_buf, VB2_BUF_STATE_ERROR);
   1114	}
   1115}
   1116
   1117static int vidioc_s_fbuf(struct file *file, void *fh,
   1118				const struct v4l2_framebuffer *a)
   1119{
   1120	int enable = 0;
   1121	struct omap_overlay *ovl;
   1122	struct omapvideo_info *ovid;
   1123	struct omap_vout_device *vout = video_drvdata(file);
   1124	struct omap_overlay_manager_info info;
   1125	enum omap_dss_trans_key_type key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
   1126
   1127	ovid = &vout->vid_info;
   1128	ovl = ovid->overlays[0];
   1129
   1130	/* OMAP DSS doesn't support Source and Destination color
   1131	   key together */
   1132	if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY) &&
   1133			(a->flags & V4L2_FBUF_FLAG_CHROMAKEY))
   1134		return -EINVAL;
   1135	/* OMAP DSS Doesn't support the Destination color key
   1136	   and alpha blending together */
   1137	if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY) &&
   1138			(a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA))
   1139		return -EINVAL;
   1140
   1141	if ((a->flags & V4L2_FBUF_FLAG_SRC_CHROMAKEY)) {
   1142		vout->fbuf.flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY;
   1143		key_type =  OMAP_DSS_COLOR_KEY_VID_SRC;
   1144	} else
   1145		vout->fbuf.flags &= ~V4L2_FBUF_FLAG_SRC_CHROMAKEY;
   1146
   1147	if ((a->flags & V4L2_FBUF_FLAG_CHROMAKEY)) {
   1148		vout->fbuf.flags |= V4L2_FBUF_FLAG_CHROMAKEY;
   1149		key_type =  OMAP_DSS_COLOR_KEY_GFX_DST;
   1150	} else
   1151		vout->fbuf.flags &=  ~V4L2_FBUF_FLAG_CHROMAKEY;
   1152
   1153	if (a->flags & (V4L2_FBUF_FLAG_CHROMAKEY |
   1154				V4L2_FBUF_FLAG_SRC_CHROMAKEY))
   1155		enable = 1;
   1156	else
   1157		enable = 0;
   1158	if (ovl->manager && ovl->manager->get_manager_info &&
   1159			ovl->manager->set_manager_info) {
   1160
   1161		ovl->manager->get_manager_info(ovl->manager, &info);
   1162		info.trans_enabled = enable;
   1163		info.trans_key_type = key_type;
   1164		info.trans_key = vout->win.chromakey;
   1165
   1166		if (ovl->manager->set_manager_info(ovl->manager, &info))
   1167			return -EINVAL;
   1168	}
   1169	if (a->flags & V4L2_FBUF_FLAG_LOCAL_ALPHA) {
   1170		vout->fbuf.flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
   1171		enable = 1;
   1172	} else {
   1173		vout->fbuf.flags &= ~V4L2_FBUF_FLAG_LOCAL_ALPHA;
   1174		enable = 0;
   1175	}
   1176	if (ovl->manager && ovl->manager->get_manager_info &&
   1177			ovl->manager->set_manager_info) {
   1178		ovl->manager->get_manager_info(ovl->manager, &info);
   1179		/* enable this only if there is no zorder cap */
   1180		if ((ovl->caps & OMAP_DSS_OVL_CAP_ZORDER) == 0)
   1181			info.partial_alpha_enabled = enable;
   1182		if (ovl->manager->set_manager_info(ovl->manager, &info))
   1183			return -EINVAL;
   1184	}
   1185
   1186	return 0;
   1187}
   1188
   1189static int vidioc_g_fbuf(struct file *file, void *fh,
   1190		struct v4l2_framebuffer *a)
   1191{
   1192	struct omap_overlay *ovl;
   1193	struct omapvideo_info *ovid;
   1194	struct omap_vout_device *vout = video_drvdata(file);
   1195	struct omap_overlay_manager_info info;
   1196	struct omap_video_timings *timing;
   1197	struct omap_dss_device *dssdev;
   1198
   1199	ovid = &vout->vid_info;
   1200	ovl = ovid->overlays[0];
   1201	/* get the display device attached to the overlay */
   1202	dssdev = ovl->get_device(ovl);
   1203
   1204	if (!dssdev)
   1205		return -EINVAL;
   1206
   1207	timing = &dssdev->panel.timings;
   1208
   1209	vout->fbuf.fmt.height = timing->y_res;
   1210	vout->fbuf.fmt.width = timing->x_res;
   1211	a->fmt.field = V4L2_FIELD_NONE;
   1212	a->fmt.colorspace = V4L2_COLORSPACE_SRGB;
   1213	a->fmt.pixelformat = V4L2_PIX_FMT_RGBA32;
   1214	a->fmt.height = vout->fbuf.fmt.height;
   1215	a->fmt.width = vout->fbuf.fmt.width;
   1216	a->fmt.bytesperline = vout->fbuf.fmt.width * 4;
   1217	a->fmt.sizeimage = a->fmt.height * a->fmt.bytesperline;
   1218	a->base = vout->fbuf.base;
   1219
   1220	a->flags = vout->fbuf.flags;
   1221	a->capability = vout->fbuf.capability;
   1222	a->flags &= ~(V4L2_FBUF_FLAG_SRC_CHROMAKEY | V4L2_FBUF_FLAG_CHROMAKEY |
   1223		      V4L2_FBUF_FLAG_LOCAL_ALPHA);
   1224
   1225	if (ovl->manager && ovl->manager->get_manager_info) {
   1226		ovl->manager->get_manager_info(ovl->manager, &info);
   1227		if (info.trans_key_type == OMAP_DSS_COLOR_KEY_VID_SRC)
   1228			a->flags |= V4L2_FBUF_FLAG_SRC_CHROMAKEY;
   1229		if (info.trans_key_type == OMAP_DSS_COLOR_KEY_GFX_DST)
   1230			a->flags |= V4L2_FBUF_FLAG_CHROMAKEY;
   1231		if (info.partial_alpha_enabled)
   1232			a->flags |= V4L2_FBUF_FLAG_LOCAL_ALPHA;
   1233	}
   1234
   1235	return 0;
   1236}
   1237
   1238static int vidioc_enum_output(struct file *file, void *priv_fh,
   1239			      struct v4l2_output *out)
   1240{
   1241	if (out->index)
   1242		return -EINVAL;
   1243	snprintf(out->name, sizeof(out->name), "Overlay");
   1244	out->type = V4L2_OUTPUT_TYPE_ANALOGVGAOVERLAY;
   1245	return 0;
   1246}
   1247
   1248static int vidioc_g_output(struct file *file, void *priv_fh, unsigned int *i)
   1249{
   1250	*i = 0;
   1251	return 0;
   1252}
   1253
   1254static int vidioc_s_output(struct file *file, void *priv_fh, unsigned int i)
   1255{
   1256	return i ? -EINVAL : 0;
   1257}
   1258
   1259static const struct v4l2_ioctl_ops vout_ioctl_ops = {
   1260	.vidioc_querycap			= vidioc_querycap,
   1261	.vidioc_enum_fmt_vid_out		= vidioc_enum_fmt_vid_out,
   1262	.vidioc_g_fmt_vid_out			= vidioc_g_fmt_vid_out,
   1263	.vidioc_try_fmt_vid_out			= vidioc_try_fmt_vid_out,
   1264	.vidioc_s_fmt_vid_out			= vidioc_s_fmt_vid_out,
   1265	.vidioc_s_fbuf				= vidioc_s_fbuf,
   1266	.vidioc_g_fbuf				= vidioc_g_fbuf,
   1267	.vidioc_try_fmt_vid_out_overlay		= vidioc_try_fmt_vid_overlay,
   1268	.vidioc_s_fmt_vid_out_overlay		= vidioc_s_fmt_vid_overlay,
   1269	.vidioc_g_fmt_vid_out_overlay		= vidioc_g_fmt_vid_overlay,
   1270	.vidioc_g_selection			= vidioc_g_selection,
   1271	.vidioc_s_selection			= vidioc_s_selection,
   1272	.vidioc_enum_output			= vidioc_enum_output,
   1273	.vidioc_g_output			= vidioc_g_output,
   1274	.vidioc_s_output			= vidioc_s_output,
   1275	.vidioc_reqbufs				= vb2_ioctl_reqbufs,
   1276	.vidioc_create_bufs			= vb2_ioctl_create_bufs,
   1277	.vidioc_querybuf			= vb2_ioctl_querybuf,
   1278	.vidioc_qbuf				= vb2_ioctl_qbuf,
   1279	.vidioc_dqbuf				= vb2_ioctl_dqbuf,
   1280	.vidioc_expbuf				= vb2_ioctl_expbuf,
   1281	.vidioc_streamon			= vb2_ioctl_streamon,
   1282	.vidioc_streamoff			= vb2_ioctl_streamoff,
   1283	.vidioc_subscribe_event			= v4l2_ctrl_subscribe_event,
   1284	.vidioc_unsubscribe_event		= v4l2_event_unsubscribe,
   1285};
   1286
   1287static const struct v4l2_file_operations omap_vout_fops = {
   1288	.owner		= THIS_MODULE,
   1289	.unlocked_ioctl	= video_ioctl2,
   1290	.poll		= vb2_fop_poll,
   1291	.mmap		= vb2_fop_mmap,
   1292	.open		= v4l2_fh_open,
   1293	.release	= vb2_fop_release,
   1294};
   1295
   1296static const struct vb2_ops omap_vout_vb2_ops = {
   1297	.queue_setup		= omap_vout_vb2_queue_setup,
   1298	.buf_queue		= omap_vout_vb2_queue,
   1299	.buf_prepare		= omap_vout_vb2_prepare,
   1300	.start_streaming	= omap_vout_vb2_start_streaming,
   1301	.stop_streaming		= omap_vout_vb2_stop_streaming,
   1302	.wait_prepare		= vb2_ops_wait_prepare,
   1303	.wait_finish		= vb2_ops_wait_finish,
   1304};
   1305
   1306/* Init functions used during driver initialization */
   1307/* Initial setup of video_data */
   1308static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
   1309{
   1310	struct video_device *vfd;
   1311	struct v4l2_pix_format *pix;
   1312	struct omap_overlay *ovl = vout->vid_info.overlays[0];
   1313	struct omap_dss_device *display = ovl->get_device(ovl);
   1314	struct v4l2_ctrl_handler *hdl;
   1315	struct vb2_queue *vq;
   1316	int ret;
   1317
   1318	/* set the default pix */
   1319	pix = &vout->pix;
   1320
   1321	/* Set the default picture of QVGA  */
   1322	pix->width = QQVGA_WIDTH;
   1323	pix->height = QQVGA_HEIGHT;
   1324
   1325	/* Default pixel format is RGB 5-6-5 */
   1326	pix->pixelformat = V4L2_PIX_FMT_RGB565;
   1327	pix->field = V4L2_FIELD_NONE;
   1328	pix->bytesperline = pix->width * 2;
   1329	pix->sizeimage = pix->bytesperline * pix->height;
   1330	pix->colorspace = V4L2_COLORSPACE_SRGB;
   1331
   1332	vout->bpp = RGB565_BPP;
   1333	vout->fbuf.fmt.width  =  display->panel.timings.x_res;
   1334	vout->fbuf.fmt.height =  display->panel.timings.y_res;
   1335	vout->cropped_offset = 0;
   1336
   1337	/* Set the data structures for the overlay parameters*/
   1338	vout->fbuf.flags = V4L2_FBUF_FLAG_OVERLAY;
   1339	vout->fbuf.capability = V4L2_FBUF_CAP_LOCAL_ALPHA |
   1340		V4L2_FBUF_CAP_SRC_CHROMAKEY | V4L2_FBUF_CAP_CHROMAKEY |
   1341		V4L2_FBUF_CAP_EXTERNOVERLAY;
   1342	if (ovl->caps & OMAP_DSS_OVL_CAP_GLOBAL_ALPHA) {
   1343		vout->win.global_alpha = 255;
   1344		vout->fbuf.capability |= V4L2_FBUF_CAP_GLOBAL_ALPHA;
   1345		vout->fbuf.flags |= V4L2_FBUF_FLAG_GLOBAL_ALPHA;
   1346	} else {
   1347		vout->win.global_alpha = 0;
   1348	}
   1349	vout->win.field = V4L2_FIELD_NONE;
   1350
   1351	omap_vout_new_format(pix, &vout->fbuf, &vout->crop, &vout->win);
   1352
   1353	hdl = &vout->ctrl_handler;
   1354	v4l2_ctrl_handler_init(hdl, 3);
   1355	if (vout->vid_info.rotation_type == VOUT_ROT_VRFB) {
   1356		v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops,
   1357				  V4L2_CID_ROTATE, 0, 270, 90, 0);
   1358		v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops,
   1359				  V4L2_CID_VFLIP, 0, 1, 1, 0);
   1360	}
   1361	v4l2_ctrl_new_std(hdl, &omap_vout_ctrl_ops,
   1362			  V4L2_CID_BG_COLOR, 0, 0xffffff, 1, 0);
   1363	if (hdl->error)
   1364		return hdl->error;
   1365
   1366	vout->rotation = 0;
   1367	vout->mirror = false;
   1368	INIT_LIST_HEAD(&vout->dma_queue);
   1369	if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
   1370		vout->vrfb_bpp = 2;
   1371
   1372	/* initialize the video_device struct */
   1373	vfd = vout->vfd = video_device_alloc();
   1374
   1375	if (!vfd) {
   1376		printk(KERN_ERR VOUT_NAME
   1377		       ": could not allocate video device struct\n");
   1378		v4l2_ctrl_handler_free(hdl);
   1379		return -ENOMEM;
   1380	}
   1381	vfd->ctrl_handler = hdl;
   1382	vfd->release = video_device_release;
   1383	vfd->ioctl_ops = &vout_ioctl_ops;
   1384
   1385	strscpy(vfd->name, VOUT_NAME, sizeof(vfd->name));
   1386
   1387	vfd->fops = &omap_vout_fops;
   1388	vfd->v4l2_dev = &vout->vid_dev->v4l2_dev;
   1389	vfd->vfl_dir = VFL_DIR_TX;
   1390	vfd->minor = -1;
   1391	vfd->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT |
   1392			   V4L2_CAP_VIDEO_OUTPUT_OVERLAY;
   1393	mutex_init(&vout->lock);
   1394
   1395	vq = &vout->vq;
   1396	vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
   1397	vq->io_modes = VB2_MMAP | VB2_DMABUF;
   1398	vq->drv_priv = vout;
   1399	vq->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
   1400	vq->buf_struct_size = sizeof(struct omap_vout_buffer);
   1401	vq->dev = vfd->v4l2_dev->dev;
   1402
   1403	vq->ops = &omap_vout_vb2_ops;
   1404	vq->mem_ops = &vb2_dma_contig_memops;
   1405	vq->lock = &vout->lock;
   1406	vq->min_buffers_needed = 1;
   1407	vfd->queue = vq;
   1408
   1409	ret = vb2_queue_init(vq);
   1410	if (ret) {
   1411		v4l2_ctrl_handler_free(hdl);
   1412		video_device_release(vfd);
   1413	}
   1414	return ret;
   1415}
   1416
   1417/* Setup video buffers */
   1418static int __init omap_vout_setup_video_bufs(struct platform_device *pdev,
   1419		int vid_num)
   1420{
   1421	struct omapvideo_info *ovid;
   1422	struct omap_vout_device *vout;
   1423	struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
   1424	struct omap2video_device *vid_dev =
   1425		container_of(v4l2_dev, struct omap2video_device, v4l2_dev);
   1426	int ret = 0;
   1427
   1428	vout = vid_dev->vouts[vid_num];
   1429	ovid = &vout->vid_info;
   1430
   1431	if (ovid->rotation_type == VOUT_ROT_VRFB) {
   1432		bool static_vrfb_allocation = (vid_num == 0) ?
   1433			vid1_static_vrfb_alloc : vid2_static_vrfb_alloc;
   1434		ret = omap_vout_setup_vrfb_bufs(pdev, vid_num,
   1435				static_vrfb_allocation);
   1436	}
   1437	return ret;
   1438}
   1439
   1440/* Create video out devices */
   1441static int __init omap_vout_create_video_devices(struct platform_device *pdev)
   1442{
   1443	int ret = 0, k;
   1444	struct omap_vout_device *vout;
   1445	struct video_device *vfd = NULL;
   1446	struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
   1447	struct omap2video_device *vid_dev = container_of(v4l2_dev,
   1448			struct omap2video_device, v4l2_dev);
   1449	struct omap_overlay *ovl = vid_dev->overlays[0];
   1450	struct omap_overlay_info info;
   1451
   1452	ovl->get_overlay_info(ovl, &info);
   1453
   1454	for (k = 0; k < pdev->num_resources; k++) {
   1455
   1456		vout = kzalloc(sizeof(struct omap_vout_device), GFP_KERNEL);
   1457		if (!vout) {
   1458			dev_err(&pdev->dev, ": could not allocate memory\n");
   1459			return -ENOMEM;
   1460		}
   1461
   1462		vout->vid = k;
   1463		vid_dev->vouts[k] = vout;
   1464		vout->vid_dev = vid_dev;
   1465		/* Select video2 if only 1 overlay is controlled by V4L2 */
   1466		if (pdev->num_resources == 1)
   1467			vout->vid_info.overlays[0] = vid_dev->overlays[k + 2];
   1468		else
   1469			/* Else select video1 and video2 one by one. */
   1470			vout->vid_info.overlays[0] = vid_dev->overlays[k + 1];
   1471		vout->vid_info.num_overlays = 1;
   1472		vout->vid_info.id = k + 1;
   1473		spin_lock_init(&vout->vbq_lock);
   1474		/*
   1475		 * Set the framebuffer base, this allows applications to find
   1476		 * the fb corresponding to this overlay.
   1477		 *
   1478		 * To be precise: fbuf.base should match smem_start of
   1479		 * struct fb_fix_screeninfo.
   1480		 */
   1481		vout->fbuf.base = (void *)(uintptr_t)info.paddr;
   1482
   1483		/* Set VRFB as rotation_type for omap2 and omap3 */
   1484		if (omap_vout_dss_omap24xx() || omap_vout_dss_omap34xx())
   1485			vout->vid_info.rotation_type = VOUT_ROT_VRFB;
   1486
   1487		/* Setup the default configuration for the video devices
   1488		 */
   1489		if (omap_vout_setup_video_data(vout) != 0) {
   1490			ret = -ENOMEM;
   1491			goto error;
   1492		}
   1493
   1494		/* Allocate default number of buffers for the video streaming
   1495		 * and reserve the VRFB space for rotation
   1496		 */
   1497		if (omap_vout_setup_video_bufs(pdev, k) != 0) {
   1498			ret = -ENOMEM;
   1499			goto error1;
   1500		}
   1501
   1502		/* Register the Video device with V4L2
   1503		 */
   1504		vfd = vout->vfd;
   1505		if (video_register_device(vfd, VFL_TYPE_VIDEO, -1) < 0) {
   1506			dev_err(&pdev->dev,
   1507				": Could not register Video for Linux device\n");
   1508			vfd->minor = -1;
   1509			ret = -ENODEV;
   1510			goto error2;
   1511		}
   1512		video_set_drvdata(vfd, vout);
   1513
   1514		dev_info(&pdev->dev,
   1515			 ": registered and initialized video device %d\n",
   1516			 vfd->minor);
   1517		if (k == (pdev->num_resources - 1))
   1518			return 0;
   1519
   1520		continue;
   1521error2:
   1522		if (vout->vid_info.rotation_type == VOUT_ROT_VRFB)
   1523			omap_vout_release_vrfb(vout);
   1524error1:
   1525		video_device_release(vfd);
   1526error:
   1527		kfree(vout);
   1528		return ret;
   1529	}
   1530
   1531	return -ENODEV;
   1532}
   1533/* Driver functions */
   1534static void omap_vout_cleanup_device(struct omap_vout_device *vout)
   1535{
   1536	struct video_device *vfd;
   1537	struct omapvideo_info *ovid;
   1538
   1539	if (!vout)
   1540		return;
   1541
   1542	vfd = vout->vfd;
   1543	ovid = &vout->vid_info;
   1544	if (vfd) {
   1545		if (!video_is_registered(vfd)) {
   1546			/*
   1547			 * The device was never registered, so release the
   1548			 * video_device struct directly.
   1549			 */
   1550			video_device_release(vfd);
   1551		} else {
   1552			/*
   1553			 * The unregister function will release the video_device
   1554			 * struct as well as unregistering it.
   1555			 */
   1556			video_unregister_device(vfd);
   1557		}
   1558	}
   1559	v4l2_ctrl_handler_free(&vout->ctrl_handler);
   1560	if (ovid->rotation_type == VOUT_ROT_VRFB) {
   1561		omap_vout_release_vrfb(vout);
   1562		/* Free the VRFB buffer if allocated
   1563		 * init time
   1564		 */
   1565		if (vout->vrfb_static_allocation)
   1566			omap_vout_free_vrfb_buffers(vout);
   1567	}
   1568
   1569	kfree(vout);
   1570}
   1571
   1572static int omap_vout_remove(struct platform_device *pdev)
   1573{
   1574	int k;
   1575	struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
   1576	struct omap2video_device *vid_dev = container_of(v4l2_dev, struct
   1577			omap2video_device, v4l2_dev);
   1578
   1579	v4l2_device_unregister(v4l2_dev);
   1580	for (k = 0; k < pdev->num_resources; k++)
   1581		omap_vout_cleanup_device(vid_dev->vouts[k]);
   1582
   1583	for (k = 0; k < vid_dev->num_displays; k++) {
   1584		if (vid_dev->displays[k]->state != OMAP_DSS_DISPLAY_DISABLED)
   1585			vid_dev->displays[k]->driver->disable(vid_dev->displays[k]);
   1586
   1587		omap_dss_put_device(vid_dev->displays[k]);
   1588	}
   1589	kfree(vid_dev);
   1590	return 0;
   1591}
   1592
   1593static int __init omap_vout_probe(struct platform_device *pdev)
   1594{
   1595	int ret = 0, i;
   1596	struct omap_overlay *ovl;
   1597	struct omap_dss_device *dssdev = NULL;
   1598	struct omap_dss_device *def_display;
   1599	struct omap2video_device *vid_dev = NULL;
   1600
   1601	if (omapdss_is_initialized() == false)
   1602		return -EPROBE_DEFER;
   1603
   1604	ret = omapdss_compat_init();
   1605	if (ret) {
   1606		dev_err(&pdev->dev, "failed to init dss\n");
   1607		return ret;
   1608	}
   1609
   1610	if (pdev->num_resources == 0) {
   1611		dev_err(&pdev->dev, "probed for an unknown device\n");
   1612		ret = -ENODEV;
   1613		goto err_dss_init;
   1614	}
   1615
   1616	vid_dev = kzalloc(sizeof(struct omap2video_device), GFP_KERNEL);
   1617	if (vid_dev == NULL) {
   1618		ret = -ENOMEM;
   1619		goto err_dss_init;
   1620	}
   1621
   1622	vid_dev->num_displays = 0;
   1623	for_each_dss_dev(dssdev) {
   1624		omap_dss_get_device(dssdev);
   1625
   1626		if (!dssdev->driver) {
   1627			dev_warn(&pdev->dev, "no driver for display: %s\n",
   1628					dssdev->name);
   1629			omap_dss_put_device(dssdev);
   1630			continue;
   1631		}
   1632
   1633		vid_dev->displays[vid_dev->num_displays++] = dssdev;
   1634	}
   1635
   1636	if (vid_dev->num_displays == 0) {
   1637		dev_err(&pdev->dev, "no displays\n");
   1638		ret = -EINVAL;
   1639		goto probe_err0;
   1640	}
   1641
   1642	vid_dev->num_overlays = omap_dss_get_num_overlays();
   1643	for (i = 0; i < vid_dev->num_overlays; i++)
   1644		vid_dev->overlays[i] = omap_dss_get_overlay(i);
   1645
   1646	vid_dev->num_managers = omap_dss_get_num_overlay_managers();
   1647	for (i = 0; i < vid_dev->num_managers; i++)
   1648		vid_dev->managers[i] = omap_dss_get_overlay_manager(i);
   1649
   1650	/* Get the Video1 overlay and video2 overlay.
   1651	 * Setup the Display attached to that overlays
   1652	 */
   1653	for (i = 1; i < vid_dev->num_overlays; i++) {
   1654		ovl = omap_dss_get_overlay(i);
   1655		dssdev = ovl->get_device(ovl);
   1656
   1657		if (dssdev) {
   1658			def_display = dssdev;
   1659		} else {
   1660			dev_warn(&pdev->dev, "cannot find display\n");
   1661			def_display = NULL;
   1662		}
   1663		if (def_display) {
   1664			struct omap_dss_driver *dssdrv = def_display->driver;
   1665
   1666			ret = dssdrv->enable(def_display);
   1667			if (ret) {
   1668				/* Here we are not considering a error
   1669				 *  as display may be enabled by frame
   1670				 *  buffer driver
   1671				 */
   1672				dev_warn(&pdev->dev,
   1673					"'%s' Display already enabled\n",
   1674					def_display->name);
   1675			}
   1676		}
   1677	}
   1678
   1679	if (v4l2_device_register(&pdev->dev, &vid_dev->v4l2_dev) < 0) {
   1680		dev_err(&pdev->dev, "v4l2_device_register failed\n");
   1681		ret = -ENODEV;
   1682		goto probe_err1;
   1683	}
   1684
   1685	ret = omap_vout_create_video_devices(pdev);
   1686	if (ret)
   1687		goto probe_err2;
   1688
   1689	for (i = 0; i < vid_dev->num_displays; i++) {
   1690		struct omap_dss_device *display = vid_dev->displays[i];
   1691
   1692		if (display->driver->update)
   1693			display->driver->update(display, 0, 0,
   1694					display->panel.timings.x_res,
   1695					display->panel.timings.y_res);
   1696	}
   1697	return 0;
   1698
   1699probe_err2:
   1700	v4l2_device_unregister(&vid_dev->v4l2_dev);
   1701probe_err1:
   1702	for (i = 1; i < vid_dev->num_overlays; i++) {
   1703		def_display = NULL;
   1704		ovl = omap_dss_get_overlay(i);
   1705		dssdev = ovl->get_device(ovl);
   1706
   1707		if (dssdev)
   1708			def_display = dssdev;
   1709
   1710		if (def_display && def_display->driver)
   1711			def_display->driver->disable(def_display);
   1712	}
   1713probe_err0:
   1714	kfree(vid_dev);
   1715err_dss_init:
   1716	omapdss_compat_uninit();
   1717	return ret;
   1718}
   1719
   1720static struct platform_driver omap_vout_driver = {
   1721	.driver = {
   1722		.name = VOUT_NAME,
   1723	},
   1724	.remove = omap_vout_remove,
   1725};
   1726
   1727static int __init omap_vout_init(void)
   1728{
   1729	if (platform_driver_probe(&omap_vout_driver, omap_vout_probe) != 0) {
   1730		printk(KERN_ERR VOUT_NAME ":Could not register Video driver\n");
   1731		return -EINVAL;
   1732	}
   1733	return 0;
   1734}
   1735
   1736static void omap_vout_cleanup(void)
   1737{
   1738	platform_driver_unregister(&omap_vout_driver);
   1739}
   1740
   1741late_initcall(omap_vout_init);
   1742module_exit(omap_vout_cleanup);