• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * SuperH Video Output Unit (VOU) driver
3  *
4  * Copyright (C) 2010, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10 
11 #include <linux/dma-mapping.h>
12 #include <linux/delay.h>
13 #include <linux/errno.h>
14 #include <linux/fs.h>
15 #include <linux/i2c.h>
16 #include <linux/init.h>
17 #include <linux/interrupt.h>
18 #include <linux/kernel.h>
19 #include <linux/platform_device.h>
20 #include <linux/pm_runtime.h>
21 #include <linux/slab.h>
22 #include <linux/videodev2.h>
23 #include <linux/module.h>
24 
25 #include <media/sh_vou.h>
26 #include <media/v4l2-common.h>
27 #include <media/v4l2-device.h>
28 #include <media/v4l2-ioctl.h>
29 #include <media/v4l2-mediabus.h>
30 #include <media/videobuf2-v4l2.h>
31 #include <media/videobuf2-dma-contig.h>
32 
33 /* Mirror addresses are not available for all registers */
34 #define VOUER	0
35 #define VOUCR	4
36 #define VOUSTR	8
37 #define VOUVCR	0xc
38 #define VOUISR	0x10
39 #define VOUBCR	0x14
40 #define VOUDPR	0x18
41 #define VOUDSR	0x1c
42 #define VOUVPR	0x20
43 #define VOUIR	0x24
44 #define VOUSRR	0x28
45 #define VOUMSR	0x2c
46 #define VOUHIR	0x30
47 #define VOUDFR	0x34
48 #define VOUAD1R	0x38
49 #define VOUAD2R	0x3c
50 #define VOUAIR	0x40
51 #define VOUSWR	0x44
52 #define VOURCR	0x48
53 #define VOURPR	0x50
54 
55 enum sh_vou_status {
56 	SH_VOU_IDLE,
57 	SH_VOU_INITIALISING,
58 	SH_VOU_RUNNING,
59 };
60 
61 #define VOU_MIN_IMAGE_WIDTH	16
62 #define VOU_MAX_IMAGE_WIDTH	720
63 #define VOU_MIN_IMAGE_HEIGHT	16
64 
65 struct sh_vou_buffer {
66 	struct vb2_v4l2_buffer vb;
67 	struct list_head list;
68 };
69 
70 static inline struct
to_sh_vou_buffer(struct vb2_v4l2_buffer * vb2)71 sh_vou_buffer *to_sh_vou_buffer(struct vb2_v4l2_buffer *vb2)
72 {
73 	return container_of(vb2, struct sh_vou_buffer, vb);
74 }
75 
76 struct sh_vou_device {
77 	struct v4l2_device v4l2_dev;
78 	struct video_device vdev;
79 	struct sh_vou_pdata *pdata;
80 	spinlock_t lock;
81 	void __iomem *base;
82 	/* State information */
83 	struct v4l2_pix_format pix;
84 	struct v4l2_rect rect;
85 	struct list_head buf_list;
86 	v4l2_std_id std;
87 	int pix_idx;
88 	struct vb2_queue queue;
89 	struct vb2_alloc_ctx *alloc_ctx;
90 	struct sh_vou_buffer *active;
91 	enum sh_vou_status status;
92 	unsigned sequence;
93 	struct mutex fop_lock;
94 };
95 
96 /* Register access routines for sides A, B and mirror addresses */
sh_vou_reg_a_write(struct sh_vou_device * vou_dev,unsigned int reg,u32 value)97 static void sh_vou_reg_a_write(struct sh_vou_device *vou_dev, unsigned int reg,
98 			       u32 value)
99 {
100 	__raw_writel(value, vou_dev->base + reg);
101 }
102 
sh_vou_reg_ab_write(struct sh_vou_device * vou_dev,unsigned int reg,u32 value)103 static void sh_vou_reg_ab_write(struct sh_vou_device *vou_dev, unsigned int reg,
104 				u32 value)
105 {
106 	__raw_writel(value, vou_dev->base + reg);
107 	__raw_writel(value, vou_dev->base + reg + 0x1000);
108 }
109 
sh_vou_reg_m_write(struct sh_vou_device * vou_dev,unsigned int reg,u32 value)110 static void sh_vou_reg_m_write(struct sh_vou_device *vou_dev, unsigned int reg,
111 			       u32 value)
112 {
113 	__raw_writel(value, vou_dev->base + reg + 0x2000);
114 }
115 
sh_vou_reg_a_read(struct sh_vou_device * vou_dev,unsigned int reg)116 static u32 sh_vou_reg_a_read(struct sh_vou_device *vou_dev, unsigned int reg)
117 {
118 	return __raw_readl(vou_dev->base + reg);
119 }
120 
sh_vou_reg_a_set(struct sh_vou_device * vou_dev,unsigned int reg,u32 value,u32 mask)121 static void sh_vou_reg_a_set(struct sh_vou_device *vou_dev, unsigned int reg,
122 			     u32 value, u32 mask)
123 {
124 	u32 old = __raw_readl(vou_dev->base + reg);
125 
126 	value = (value & mask) | (old & ~mask);
127 	__raw_writel(value, vou_dev->base + reg);
128 }
129 
sh_vou_reg_b_set(struct sh_vou_device * vou_dev,unsigned int reg,u32 value,u32 mask)130 static void sh_vou_reg_b_set(struct sh_vou_device *vou_dev, unsigned int reg,
131 			     u32 value, u32 mask)
132 {
133 	sh_vou_reg_a_set(vou_dev, reg + 0x1000, value, mask);
134 }
135 
sh_vou_reg_ab_set(struct sh_vou_device * vou_dev,unsigned int reg,u32 value,u32 mask)136 static void sh_vou_reg_ab_set(struct sh_vou_device *vou_dev, unsigned int reg,
137 			      u32 value, u32 mask)
138 {
139 	sh_vou_reg_a_set(vou_dev, reg, value, mask);
140 	sh_vou_reg_b_set(vou_dev, reg, value, mask);
141 }
142 
143 struct sh_vou_fmt {
144 	u32		pfmt;
145 	char		*desc;
146 	unsigned char	bpp;
147 	unsigned char	bpl;
148 	unsigned char	rgb;
149 	unsigned char	yf;
150 	unsigned char	pkf;
151 };
152 
153 /* Further pixel formats can be added */
154 static struct sh_vou_fmt vou_fmt[] = {
155 	{
156 		.pfmt	= V4L2_PIX_FMT_NV12,
157 		.bpp	= 12,
158 		.bpl	= 1,
159 		.desc	= "YVU420 planar",
160 		.yf	= 0,
161 		.rgb	= 0,
162 	},
163 	{
164 		.pfmt	= V4L2_PIX_FMT_NV16,
165 		.bpp	= 16,
166 		.bpl	= 1,
167 		.desc	= "YVYU planar",
168 		.yf	= 1,
169 		.rgb	= 0,
170 	},
171 	{
172 		.pfmt	= V4L2_PIX_FMT_RGB24,
173 		.bpp	= 24,
174 		.bpl	= 3,
175 		.desc	= "RGB24",
176 		.pkf	= 2,
177 		.rgb	= 1,
178 	},
179 	{
180 		.pfmt	= V4L2_PIX_FMT_RGB565,
181 		.bpp	= 16,
182 		.bpl	= 2,
183 		.desc	= "RGB565",
184 		.pkf	= 3,
185 		.rgb	= 1,
186 	},
187 	{
188 		.pfmt	= V4L2_PIX_FMT_RGB565X,
189 		.bpp	= 16,
190 		.bpl	= 2,
191 		.desc	= "RGB565 byteswapped",
192 		.pkf	= 3,
193 		.rgb	= 1,
194 	},
195 };
196 
sh_vou_schedule_next(struct sh_vou_device * vou_dev,struct vb2_v4l2_buffer * vbuf)197 static void sh_vou_schedule_next(struct sh_vou_device *vou_dev,
198 				 struct vb2_v4l2_buffer *vbuf)
199 {
200 	dma_addr_t addr1, addr2;
201 
202 	addr1 = vb2_dma_contig_plane_dma_addr(&vbuf->vb2_buf, 0);
203 	switch (vou_dev->pix.pixelformat) {
204 	case V4L2_PIX_FMT_NV12:
205 	case V4L2_PIX_FMT_NV16:
206 		addr2 = addr1 + vou_dev->pix.width * vou_dev->pix.height;
207 		break;
208 	default:
209 		addr2 = 0;
210 	}
211 
212 	sh_vou_reg_m_write(vou_dev, VOUAD1R, addr1);
213 	sh_vou_reg_m_write(vou_dev, VOUAD2R, addr2);
214 }
215 
sh_vou_stream_config(struct sh_vou_device * vou_dev)216 static void sh_vou_stream_config(struct sh_vou_device *vou_dev)
217 {
218 	unsigned int row_coeff;
219 #ifdef __LITTLE_ENDIAN
220 	u32 dataswap = 7;
221 #else
222 	u32 dataswap = 0;
223 #endif
224 
225 	switch (vou_dev->pix.pixelformat) {
226 	default:
227 	case V4L2_PIX_FMT_NV12:
228 	case V4L2_PIX_FMT_NV16:
229 		row_coeff = 1;
230 		break;
231 	case V4L2_PIX_FMT_RGB565:
232 		dataswap ^= 1;
233 	case V4L2_PIX_FMT_RGB565X:
234 		row_coeff = 2;
235 		break;
236 	case V4L2_PIX_FMT_RGB24:
237 		row_coeff = 3;
238 		break;
239 	}
240 
241 	sh_vou_reg_a_write(vou_dev, VOUSWR, dataswap);
242 	sh_vou_reg_ab_write(vou_dev, VOUAIR, vou_dev->pix.width * row_coeff);
243 }
244 
245 /* Locking: caller holds fop_lock mutex */
sh_vou_queue_setup(struct vb2_queue * vq,const void * parg,unsigned int * nbuffers,unsigned int * nplanes,unsigned int sizes[],void * alloc_ctxs[])246 static int sh_vou_queue_setup(struct vb2_queue *vq, const void *parg,
247 		       unsigned int *nbuffers, unsigned int *nplanes,
248 		       unsigned int sizes[], void *alloc_ctxs[])
249 {
250 	const struct v4l2_format *fmt = parg;
251 	struct sh_vou_device *vou_dev = vb2_get_drv_priv(vq);
252 	struct v4l2_pix_format *pix = &vou_dev->pix;
253 	int bytes_per_line = vou_fmt[vou_dev->pix_idx].bpp * pix->width / 8;
254 
255 	dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
256 
257 	if (fmt && fmt->fmt.pix.sizeimage < pix->height * bytes_per_line)
258 		return -EINVAL;
259 	*nplanes = 1;
260 	sizes[0] = fmt ? fmt->fmt.pix.sizeimage : pix->height * bytes_per_line;
261 	alloc_ctxs[0] = vou_dev->alloc_ctx;
262 	return 0;
263 }
264 
sh_vou_buf_prepare(struct vb2_buffer * vb)265 static int sh_vou_buf_prepare(struct vb2_buffer *vb)
266 {
267 	struct sh_vou_device *vou_dev = vb2_get_drv_priv(vb->vb2_queue);
268 	struct v4l2_pix_format *pix = &vou_dev->pix;
269 	unsigned bytes_per_line = vou_fmt[vou_dev->pix_idx].bpp * pix->width / 8;
270 	unsigned size = pix->height * bytes_per_line;
271 
272 	dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
273 
274 	if (vb2_plane_size(vb, 0) < size) {
275 		/* User buffer too small */
276 		dev_warn(vou_dev->v4l2_dev.dev, "buffer too small (%lu < %u)\n",
277 			 vb2_plane_size(vb, 0), size);
278 		return -EINVAL;
279 	}
280 
281 	vb2_set_plane_payload(vb, 0, size);
282 	return 0;
283 }
284 
285 /* Locking: caller holds fop_lock mutex and vq->irqlock spinlock */
sh_vou_buf_queue(struct vb2_buffer * vb)286 static void sh_vou_buf_queue(struct vb2_buffer *vb)
287 {
288 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
289 	struct sh_vou_device *vou_dev = vb2_get_drv_priv(vb->vb2_queue);
290 	struct sh_vou_buffer *shbuf = to_sh_vou_buffer(vbuf);
291 	unsigned long flags;
292 
293 	spin_lock_irqsave(&vou_dev->lock, flags);
294 	list_add_tail(&shbuf->list, &vou_dev->buf_list);
295 	spin_unlock_irqrestore(&vou_dev->lock, flags);
296 }
297 
sh_vou_start_streaming(struct vb2_queue * vq,unsigned int count)298 static int sh_vou_start_streaming(struct vb2_queue *vq, unsigned int count)
299 {
300 	struct sh_vou_device *vou_dev = vb2_get_drv_priv(vq);
301 	struct sh_vou_buffer *buf, *node;
302 	int ret;
303 
304 	vou_dev->sequence = 0;
305 	ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0,
306 					 video, s_stream, 1);
307 	if (ret < 0 && ret != -ENOIOCTLCMD) {
308 		list_for_each_entry_safe(buf, node, &vou_dev->buf_list, list) {
309 			vb2_buffer_done(&buf->vb.vb2_buf,
310 					VB2_BUF_STATE_QUEUED);
311 			list_del(&buf->list);
312 		}
313 		vou_dev->active = NULL;
314 		return ret;
315 	}
316 
317 	buf = list_entry(vou_dev->buf_list.next, struct sh_vou_buffer, list);
318 
319 	vou_dev->active = buf;
320 
321 	/* Start from side A: we use mirror addresses, so, set B */
322 	sh_vou_reg_a_write(vou_dev, VOURPR, 1);
323 	dev_dbg(vou_dev->v4l2_dev.dev, "%s: first buffer status 0x%x\n",
324 		__func__, sh_vou_reg_a_read(vou_dev, VOUSTR));
325 	sh_vou_schedule_next(vou_dev, &buf->vb);
326 
327 	buf = list_entry(buf->list.next, struct sh_vou_buffer, list);
328 
329 	/* Second buffer - initialise register side B */
330 	sh_vou_reg_a_write(vou_dev, VOURPR, 0);
331 	sh_vou_schedule_next(vou_dev, &buf->vb);
332 
333 	/* Register side switching with frame VSYNC */
334 	sh_vou_reg_a_write(vou_dev, VOURCR, 5);
335 
336 	sh_vou_stream_config(vou_dev);
337 	/* Enable End-of-Frame (VSYNC) interrupts */
338 	sh_vou_reg_a_write(vou_dev, VOUIR, 0x10004);
339 
340 	/* Two buffers on the queue - activate the hardware */
341 	vou_dev->status = SH_VOU_RUNNING;
342 	sh_vou_reg_a_write(vou_dev, VOUER, 0x107);
343 	return 0;
344 }
345 
sh_vou_stop_streaming(struct vb2_queue * vq)346 static void sh_vou_stop_streaming(struct vb2_queue *vq)
347 {
348 	struct sh_vou_device *vou_dev = vb2_get_drv_priv(vq);
349 	struct sh_vou_buffer *buf, *node;
350 	unsigned long flags;
351 
352 	v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0,
353 					 video, s_stream, 0);
354 	/* disable output */
355 	sh_vou_reg_a_set(vou_dev, VOUER, 0, 1);
356 	/* ...but the current frame will complete */
357 	sh_vou_reg_a_set(vou_dev, VOUIR, 0, 0x30000);
358 	msleep(50);
359 	spin_lock_irqsave(&vou_dev->lock, flags);
360 	list_for_each_entry_safe(buf, node, &vou_dev->buf_list, list) {
361 		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
362 		list_del(&buf->list);
363 	}
364 	vou_dev->active = NULL;
365 	spin_unlock_irqrestore(&vou_dev->lock, flags);
366 }
367 
368 static struct vb2_ops sh_vou_qops = {
369 	.queue_setup		= sh_vou_queue_setup,
370 	.buf_prepare		= sh_vou_buf_prepare,
371 	.buf_queue		= sh_vou_buf_queue,
372 	.start_streaming	= sh_vou_start_streaming,
373 	.stop_streaming		= sh_vou_stop_streaming,
374 	.wait_prepare		= vb2_ops_wait_prepare,
375 	.wait_finish		= vb2_ops_wait_finish,
376 };
377 
378 /* Video IOCTLs */
sh_vou_querycap(struct file * file,void * priv,struct v4l2_capability * cap)379 static int sh_vou_querycap(struct file *file, void  *priv,
380 			   struct v4l2_capability *cap)
381 {
382 	struct sh_vou_device *vou_dev = video_drvdata(file);
383 
384 	dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
385 
386 	strlcpy(cap->card, "SuperH VOU", sizeof(cap->card));
387 	strlcpy(cap->driver, "sh-vou", sizeof(cap->driver));
388 	strlcpy(cap->bus_info, "platform:sh-vou", sizeof(cap->bus_info));
389 	cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_READWRITE |
390 			   V4L2_CAP_STREAMING;
391 	cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
392 	return 0;
393 }
394 
395 /* Enumerate formats, that the device can accept from the user */
sh_vou_enum_fmt_vid_out(struct file * file,void * priv,struct v4l2_fmtdesc * fmt)396 static int sh_vou_enum_fmt_vid_out(struct file *file, void  *priv,
397 				   struct v4l2_fmtdesc *fmt)
398 {
399 	struct sh_vou_device *vou_dev = video_drvdata(file);
400 
401 	if (fmt->index >= ARRAY_SIZE(vou_fmt))
402 		return -EINVAL;
403 
404 	dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
405 
406 	fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
407 	strlcpy(fmt->description, vou_fmt[fmt->index].desc,
408 		sizeof(fmt->description));
409 	fmt->pixelformat = vou_fmt[fmt->index].pfmt;
410 
411 	return 0;
412 }
413 
sh_vou_g_fmt_vid_out(struct file * file,void * priv,struct v4l2_format * fmt)414 static int sh_vou_g_fmt_vid_out(struct file *file, void *priv,
415 				struct v4l2_format *fmt)
416 {
417 	struct sh_vou_device *vou_dev = video_drvdata(file);
418 
419 	dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
420 
421 	fmt->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
422 	fmt->fmt.pix = vou_dev->pix;
423 
424 	return 0;
425 }
426 
427 static const unsigned char vou_scale_h_num[] = {1, 9, 2, 9, 4};
428 static const unsigned char vou_scale_h_den[] = {1, 8, 1, 4, 1};
429 static const unsigned char vou_scale_h_fld[] = {0, 2, 1, 3};
430 static const unsigned char vou_scale_v_num[] = {1, 2, 4};
431 static const unsigned char vou_scale_v_den[] = {1, 1, 1};
432 static const unsigned char vou_scale_v_fld[] = {0, 1};
433 
sh_vou_configure_geometry(struct sh_vou_device * vou_dev,int pix_idx,int w_idx,int h_idx)434 static void sh_vou_configure_geometry(struct sh_vou_device *vou_dev,
435 				      int pix_idx, int w_idx, int h_idx)
436 {
437 	struct sh_vou_fmt *fmt = vou_fmt + pix_idx;
438 	unsigned int black_left, black_top, width_max,
439 		frame_in_height, frame_out_height, frame_out_top;
440 	struct v4l2_rect *rect = &vou_dev->rect;
441 	struct v4l2_pix_format *pix = &vou_dev->pix;
442 	u32 vouvcr = 0, dsr_h, dsr_v;
443 
444 	if (vou_dev->std & V4L2_STD_525_60) {
445 		width_max = 858;
446 		/* height_max = 262; */
447 	} else {
448 		width_max = 864;
449 		/* height_max = 312; */
450 	}
451 
452 	frame_in_height = pix->height / 2;
453 	frame_out_height = rect->height / 2;
454 	frame_out_top = rect->top / 2;
455 
456 	/*
457 	 * Cropping scheme: max useful image is 720x480, and the total video
458 	 * area is 858x525 (NTSC) or 864x625 (PAL). AK8813 / 8814 starts
459 	 * sampling data beginning with fixed 276th (NTSC) / 288th (PAL) clock,
460 	 * of which the first 33 / 25 clocks HSYNC must be held active. This
461 	 * has to be configured in CR[HW]. 1 pixel equals 2 clock periods.
462 	 * This gives CR[HW] = 16 / 12, VPR[HVP] = 138 / 144, which gives
463 	 * exactly 858 - 138 = 864 - 144 = 720! We call the out-of-display area,
464 	 * beyond DSR, specified on the left and top by the VPR register "black
465 	 * pixels" and out-of-image area (DPR) "background pixels." We fix VPR
466 	 * at 138 / 144 : 20, because that's the HSYNC timing, that our first
467 	 * client requires, and that's exactly what leaves us 720 pixels for the
468 	 * image; we leave VPR[VVP] at default 20 for now, because the client
469 	 * doesn't seem to have any special requirements for it. Otherwise we
470 	 * could also set it to max - 240 = 22 / 72. Thus VPR depends only on
471 	 * the selected standard, and DPR and DSR are selected according to
472 	 * cropping. Q: how does the client detect the first valid line? Does
473 	 * HSYNC stay inactive during invalid (black) lines?
474 	 */
475 	black_left = width_max - VOU_MAX_IMAGE_WIDTH;
476 	black_top = 20;
477 
478 	dsr_h = rect->width + rect->left;
479 	dsr_v = frame_out_height + frame_out_top;
480 
481 	dev_dbg(vou_dev->v4l2_dev.dev,
482 		"image %ux%u, black %u:%u, offset %u:%u, display %ux%u\n",
483 		pix->width, frame_in_height, black_left, black_top,
484 		rect->left, frame_out_top, dsr_h, dsr_v);
485 
486 	/* VOUISR height - half of a frame height in frame mode */
487 	sh_vou_reg_ab_write(vou_dev, VOUISR, (pix->width << 16) | frame_in_height);
488 	sh_vou_reg_ab_write(vou_dev, VOUVPR, (black_left << 16) | black_top);
489 	sh_vou_reg_ab_write(vou_dev, VOUDPR, (rect->left << 16) | frame_out_top);
490 	sh_vou_reg_ab_write(vou_dev, VOUDSR, (dsr_h << 16) | dsr_v);
491 
492 	/*
493 	 * if necessary, we could set VOUHIR to
494 	 * max(black_left + dsr_h, width_max) here
495 	 */
496 
497 	if (w_idx)
498 		vouvcr |= (1 << 15) | (vou_scale_h_fld[w_idx - 1] << 4);
499 	if (h_idx)
500 		vouvcr |= (1 << 14) | vou_scale_v_fld[h_idx - 1];
501 
502 	dev_dbg(vou_dev->v4l2_dev.dev, "%s: scaling 0x%x\n", fmt->desc, vouvcr);
503 
504 	/* To produce a colour bar for testing set bit 23 of VOUVCR */
505 	sh_vou_reg_ab_write(vou_dev, VOUVCR, vouvcr);
506 	sh_vou_reg_ab_write(vou_dev, VOUDFR,
507 			    fmt->pkf | (fmt->yf << 8) | (fmt->rgb << 16));
508 }
509 
510 struct sh_vou_geometry {
511 	struct v4l2_rect output;
512 	unsigned int in_width;
513 	unsigned int in_height;
514 	int scale_idx_h;
515 	int scale_idx_v;
516 };
517 
518 /*
519  * Find input geometry, that we can use to produce output, closest to the
520  * requested rectangle, using VOU scaling
521  */
vou_adjust_input(struct sh_vou_geometry * geo,v4l2_std_id std)522 static void vou_adjust_input(struct sh_vou_geometry *geo, v4l2_std_id std)
523 {
524 	/* The compiler cannot know, that best and idx will indeed be set */
525 	unsigned int best_err = UINT_MAX, best = 0, img_height_max;
526 	int i, idx = 0;
527 
528 	if (std & V4L2_STD_525_60)
529 		img_height_max = 480;
530 	else
531 		img_height_max = 576;
532 
533 	/* Image width must be a multiple of 4 */
534 	v4l_bound_align_image(&geo->in_width,
535 			      VOU_MIN_IMAGE_WIDTH, VOU_MAX_IMAGE_WIDTH, 2,
536 			      &geo->in_height,
537 			      VOU_MIN_IMAGE_HEIGHT, img_height_max, 1, 0);
538 
539 	/* Select scales to come as close as possible to the output image */
540 	for (i = ARRAY_SIZE(vou_scale_h_num) - 1; i >= 0; i--) {
541 		unsigned int err;
542 		unsigned int found = geo->output.width * vou_scale_h_den[i] /
543 			vou_scale_h_num[i];
544 
545 		if (found > VOU_MAX_IMAGE_WIDTH)
546 			/* scales increase */
547 			break;
548 
549 		err = abs(found - geo->in_width);
550 		if (err < best_err) {
551 			best_err = err;
552 			idx = i;
553 			best = found;
554 		}
555 		if (!err)
556 			break;
557 	}
558 
559 	geo->in_width = best;
560 	geo->scale_idx_h = idx;
561 
562 	best_err = UINT_MAX;
563 
564 	/* This loop can be replaced with one division */
565 	for (i = ARRAY_SIZE(vou_scale_v_num) - 1; i >= 0; i--) {
566 		unsigned int err;
567 		unsigned int found = geo->output.height * vou_scale_v_den[i] /
568 			vou_scale_v_num[i];
569 
570 		if (found > img_height_max)
571 			/* scales increase */
572 			break;
573 
574 		err = abs(found - geo->in_height);
575 		if (err < best_err) {
576 			best_err = err;
577 			idx = i;
578 			best = found;
579 		}
580 		if (!err)
581 			break;
582 	}
583 
584 	geo->in_height = best;
585 	geo->scale_idx_v = idx;
586 }
587 
588 /*
589  * Find output geometry, that we can produce, using VOU scaling, closest to
590  * the requested rectangle
591  */
vou_adjust_output(struct sh_vou_geometry * geo,v4l2_std_id std)592 static void vou_adjust_output(struct sh_vou_geometry *geo, v4l2_std_id std)
593 {
594 	unsigned int best_err = UINT_MAX, best = geo->in_width,
595 		width_max, height_max, img_height_max;
596 	int i, idx_h = 0, idx_v = 0;
597 
598 	if (std & V4L2_STD_525_60) {
599 		width_max = 858;
600 		height_max = 262 * 2;
601 		img_height_max = 480;
602 	} else {
603 		width_max = 864;
604 		height_max = 312 * 2;
605 		img_height_max = 576;
606 	}
607 
608 	/* Select scales to come as close as possible to the output image */
609 	for (i = 0; i < ARRAY_SIZE(vou_scale_h_num); i++) {
610 		unsigned int err;
611 		unsigned int found = geo->in_width * vou_scale_h_num[i] /
612 			vou_scale_h_den[i];
613 
614 		if (found > VOU_MAX_IMAGE_WIDTH)
615 			/* scales increase */
616 			break;
617 
618 		err = abs(found - geo->output.width);
619 		if (err < best_err) {
620 			best_err = err;
621 			idx_h = i;
622 			best = found;
623 		}
624 		if (!err)
625 			break;
626 	}
627 
628 	geo->output.width = best;
629 	geo->scale_idx_h = idx_h;
630 	if (geo->output.left + best > width_max)
631 		geo->output.left = width_max - best;
632 
633 	pr_debug("%s(): W %u * %u/%u = %u\n", __func__, geo->in_width,
634 		 vou_scale_h_num[idx_h], vou_scale_h_den[idx_h], best);
635 
636 	best_err = UINT_MAX;
637 
638 	/* This loop can be replaced with one division */
639 	for (i = 0; i < ARRAY_SIZE(vou_scale_v_num); i++) {
640 		unsigned int err;
641 		unsigned int found = geo->in_height * vou_scale_v_num[i] /
642 			vou_scale_v_den[i];
643 
644 		if (found > img_height_max)
645 			/* scales increase */
646 			break;
647 
648 		err = abs(found - geo->output.height);
649 		if (err < best_err) {
650 			best_err = err;
651 			idx_v = i;
652 			best = found;
653 		}
654 		if (!err)
655 			break;
656 	}
657 
658 	geo->output.height = best;
659 	geo->scale_idx_v = idx_v;
660 	if (geo->output.top + best > height_max)
661 		geo->output.top = height_max - best;
662 
663 	pr_debug("%s(): H %u * %u/%u = %u\n", __func__, geo->in_height,
664 		 vou_scale_v_num[idx_v], vou_scale_v_den[idx_v], best);
665 }
666 
sh_vou_try_fmt_vid_out(struct file * file,void * priv,struct v4l2_format * fmt)667 static int sh_vou_try_fmt_vid_out(struct file *file, void *priv,
668 				  struct v4l2_format *fmt)
669 {
670 	struct sh_vou_device *vou_dev = video_drvdata(file);
671 	struct v4l2_pix_format *pix = &fmt->fmt.pix;
672 	unsigned int img_height_max;
673 	int pix_idx;
674 
675 	dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
676 
677 	pix->field = V4L2_FIELD_INTERLACED;
678 	pix->colorspace = V4L2_COLORSPACE_SMPTE170M;
679 	pix->ycbcr_enc = pix->quantization = 0;
680 
681 	for (pix_idx = 0; pix_idx < ARRAY_SIZE(vou_fmt); pix_idx++)
682 		if (vou_fmt[pix_idx].pfmt == pix->pixelformat)
683 			break;
684 
685 	if (pix_idx == ARRAY_SIZE(vou_fmt))
686 		return -EINVAL;
687 
688 	if (vou_dev->std & V4L2_STD_525_60)
689 		img_height_max = 480;
690 	else
691 		img_height_max = 576;
692 
693 	v4l_bound_align_image(&pix->width,
694 			      VOU_MIN_IMAGE_WIDTH, VOU_MAX_IMAGE_WIDTH, 2,
695 			      &pix->height,
696 			      VOU_MIN_IMAGE_HEIGHT, img_height_max, 1, 0);
697 	pix->bytesperline = pix->width * vou_fmt[pix_idx].bpl;
698 	pix->sizeimage = pix->height * ((pix->width * vou_fmt[pix_idx].bpp) >> 3);
699 
700 	return 0;
701 }
702 
sh_vou_set_fmt_vid_out(struct sh_vou_device * vou_dev,struct v4l2_pix_format * pix)703 static int sh_vou_set_fmt_vid_out(struct sh_vou_device *vou_dev,
704 				struct v4l2_pix_format *pix)
705 {
706 	unsigned int img_height_max;
707 	struct sh_vou_geometry geo;
708 	struct v4l2_subdev_format format = {
709 		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
710 		/* Revisit: is this the correct code? */
711 		.format.code = MEDIA_BUS_FMT_YUYV8_2X8,
712 		.format.field = V4L2_FIELD_INTERLACED,
713 		.format.colorspace = V4L2_COLORSPACE_SMPTE170M,
714 	};
715 	struct v4l2_mbus_framefmt *mbfmt = &format.format;
716 	int pix_idx;
717 	int ret;
718 
719 	if (vb2_is_busy(&vou_dev->queue))
720 		return -EBUSY;
721 
722 	for (pix_idx = 0; pix_idx < ARRAY_SIZE(vou_fmt); pix_idx++)
723 		if (vou_fmt[pix_idx].pfmt == pix->pixelformat)
724 			break;
725 
726 	geo.in_width = pix->width;
727 	geo.in_height = pix->height;
728 	geo.output = vou_dev->rect;
729 
730 	vou_adjust_output(&geo, vou_dev->std);
731 
732 	mbfmt->width = geo.output.width;
733 	mbfmt->height = geo.output.height;
734 	ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, pad,
735 					 set_fmt, NULL, &format);
736 	/* Must be implemented, so, don't check for -ENOIOCTLCMD */
737 	if (ret < 0)
738 		return ret;
739 
740 	dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u -> %ux%u\n", __func__,
741 		geo.output.width, geo.output.height, mbfmt->width, mbfmt->height);
742 
743 	if (vou_dev->std & V4L2_STD_525_60)
744 		img_height_max = 480;
745 	else
746 		img_height_max = 576;
747 
748 	/* Sanity checks */
749 	if ((unsigned)mbfmt->width > VOU_MAX_IMAGE_WIDTH ||
750 	    (unsigned)mbfmt->height > img_height_max ||
751 	    mbfmt->code != MEDIA_BUS_FMT_YUYV8_2X8)
752 		return -EIO;
753 
754 	if (mbfmt->width != geo.output.width ||
755 	    mbfmt->height != geo.output.height) {
756 		geo.output.width = mbfmt->width;
757 		geo.output.height = mbfmt->height;
758 
759 		vou_adjust_input(&geo, vou_dev->std);
760 	}
761 
762 	/* We tried to preserve output rectangle, but it could have changed */
763 	vou_dev->rect = geo.output;
764 	pix->width = geo.in_width;
765 	pix->height = geo.in_height;
766 
767 	dev_dbg(vou_dev->v4l2_dev.dev, "%s(): %ux%u\n", __func__,
768 		pix->width, pix->height);
769 
770 	vou_dev->pix_idx = pix_idx;
771 
772 	vou_dev->pix = *pix;
773 
774 	sh_vou_configure_geometry(vou_dev, pix_idx,
775 				  geo.scale_idx_h, geo.scale_idx_v);
776 
777 	return 0;
778 }
779 
sh_vou_s_fmt_vid_out(struct file * file,void * priv,struct v4l2_format * fmt)780 static int sh_vou_s_fmt_vid_out(struct file *file, void *priv,
781 				struct v4l2_format *fmt)
782 {
783 	struct sh_vou_device *vou_dev = video_drvdata(file);
784 	int ret = sh_vou_try_fmt_vid_out(file, priv, fmt);
785 
786 	if (ret)
787 		return ret;
788 	return sh_vou_set_fmt_vid_out(vou_dev, &fmt->fmt.pix);
789 }
790 
sh_vou_enum_output(struct file * file,void * fh,struct v4l2_output * a)791 static int sh_vou_enum_output(struct file *file, void *fh,
792 			      struct v4l2_output *a)
793 {
794 	struct sh_vou_device *vou_dev = video_drvdata(file);
795 
796 	if (a->index)
797 		return -EINVAL;
798 	strlcpy(a->name, "Video Out", sizeof(a->name));
799 	a->type = V4L2_OUTPUT_TYPE_ANALOG;
800 	a->std = vou_dev->vdev.tvnorms;
801 	return 0;
802 }
803 
sh_vou_g_output(struct file * file,void * fh,unsigned int * i)804 static int sh_vou_g_output(struct file *file, void *fh, unsigned int *i)
805 {
806 	*i = 0;
807 	return 0;
808 }
809 
sh_vou_s_output(struct file * file,void * fh,unsigned int i)810 static int sh_vou_s_output(struct file *file, void *fh, unsigned int i)
811 {
812 	return i ? -EINVAL : 0;
813 }
814 
sh_vou_ntsc_mode(enum sh_vou_bus_fmt bus_fmt)815 static u32 sh_vou_ntsc_mode(enum sh_vou_bus_fmt bus_fmt)
816 {
817 	switch (bus_fmt) {
818 	default:
819 		pr_warning("%s(): Invalid bus-format code %d, using default 8-bit\n",
820 			   __func__, bus_fmt);
821 	case SH_VOU_BUS_8BIT:
822 		return 1;
823 	case SH_VOU_BUS_16BIT:
824 		return 0;
825 	case SH_VOU_BUS_BT656:
826 		return 3;
827 	}
828 }
829 
sh_vou_s_std(struct file * file,void * priv,v4l2_std_id std_id)830 static int sh_vou_s_std(struct file *file, void *priv, v4l2_std_id std_id)
831 {
832 	struct sh_vou_device *vou_dev = video_drvdata(file);
833 	int ret;
834 
835 	dev_dbg(vou_dev->v4l2_dev.dev, "%s(): 0x%llx\n", __func__, std_id);
836 
837 	if (std_id == vou_dev->std)
838 		return 0;
839 
840 	if (vb2_is_busy(&vou_dev->queue))
841 		return -EBUSY;
842 
843 	ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video,
844 					 s_std_output, std_id);
845 	/* Shall we continue, if the subdev doesn't support .s_std_output()? */
846 	if (ret < 0 && ret != -ENOIOCTLCMD)
847 		return ret;
848 
849 	vou_dev->rect.top = vou_dev->rect.left = 0;
850 	vou_dev->rect.width = VOU_MAX_IMAGE_WIDTH;
851 	if (std_id & V4L2_STD_525_60) {
852 		sh_vou_reg_ab_set(vou_dev, VOUCR,
853 			sh_vou_ntsc_mode(vou_dev->pdata->bus_fmt) << 29, 7 << 29);
854 		vou_dev->rect.height = 480;
855 	} else {
856 		sh_vou_reg_ab_set(vou_dev, VOUCR, 5 << 29, 7 << 29);
857 		vou_dev->rect.height = 576;
858 	}
859 
860 	vou_dev->pix.width = vou_dev->rect.width;
861 	vou_dev->pix.height = vou_dev->rect.height;
862 	vou_dev->pix.bytesperline =
863 		vou_dev->pix.width * vou_fmt[vou_dev->pix_idx].bpl;
864 	vou_dev->pix.sizeimage = vou_dev->pix.height *
865 		((vou_dev->pix.width * vou_fmt[vou_dev->pix_idx].bpp) >> 3);
866 	vou_dev->std = std_id;
867 	sh_vou_set_fmt_vid_out(vou_dev, &vou_dev->pix);
868 
869 	return 0;
870 }
871 
sh_vou_g_std(struct file * file,void * priv,v4l2_std_id * std)872 static int sh_vou_g_std(struct file *file, void *priv, v4l2_std_id *std)
873 {
874 	struct sh_vou_device *vou_dev = video_drvdata(file);
875 
876 	dev_dbg(vou_dev->v4l2_dev.dev, "%s()\n", __func__);
877 
878 	*std = vou_dev->std;
879 
880 	return 0;
881 }
882 
sh_vou_log_status(struct file * file,void * priv)883 static int sh_vou_log_status(struct file *file, void *priv)
884 {
885 	struct sh_vou_device *vou_dev = video_drvdata(file);
886 
887 	pr_info("VOUER:   0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUER));
888 	pr_info("VOUCR:   0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUCR));
889 	pr_info("VOUSTR:  0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUSTR));
890 	pr_info("VOUVCR:  0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUVCR));
891 	pr_info("VOUISR:  0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUISR));
892 	pr_info("VOUBCR:  0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUBCR));
893 	pr_info("VOUDPR:  0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUDPR));
894 	pr_info("VOUDSR:  0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUDSR));
895 	pr_info("VOUVPR:  0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUVPR));
896 	pr_info("VOUIR:   0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUIR));
897 	pr_info("VOUSRR:  0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUSRR));
898 	pr_info("VOUMSR:  0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUMSR));
899 	pr_info("VOUHIR:  0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUHIR));
900 	pr_info("VOUDFR:  0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUDFR));
901 	pr_info("VOUAD1R: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUAD1R));
902 	pr_info("VOUAD2R: 0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUAD2R));
903 	pr_info("VOUAIR:  0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUAIR));
904 	pr_info("VOUSWR:  0x%08x\n", sh_vou_reg_a_read(vou_dev, VOUSWR));
905 	pr_info("VOURCR:  0x%08x\n", sh_vou_reg_a_read(vou_dev, VOURCR));
906 	pr_info("VOURPR:  0x%08x\n", sh_vou_reg_a_read(vou_dev, VOURPR));
907 	return 0;
908 }
909 
sh_vou_g_selection(struct file * file,void * fh,struct v4l2_selection * sel)910 static int sh_vou_g_selection(struct file *file, void *fh,
911 			      struct v4l2_selection *sel)
912 {
913 	struct sh_vou_device *vou_dev = video_drvdata(file);
914 
915 	if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
916 		return -EINVAL;
917 	switch (sel->target) {
918 	case V4L2_SEL_TGT_COMPOSE:
919 		sel->r = vou_dev->rect;
920 		break;
921 	case V4L2_SEL_TGT_COMPOSE_DEFAULT:
922 	case V4L2_SEL_TGT_COMPOSE_BOUNDS:
923 		sel->r.left = 0;
924 		sel->r.top = 0;
925 		sel->r.width = VOU_MAX_IMAGE_WIDTH;
926 		if (vou_dev->std & V4L2_STD_525_60)
927 			sel->r.height = 480;
928 		else
929 			sel->r.height = 576;
930 		break;
931 	default:
932 		return -EINVAL;
933 	}
934 	return 0;
935 }
936 
937 /* Assume a dull encoder, do all the work ourselves. */
sh_vou_s_selection(struct file * file,void * fh,struct v4l2_selection * sel)938 static int sh_vou_s_selection(struct file *file, void *fh,
939 			      struct v4l2_selection *sel)
940 {
941 	struct v4l2_rect *rect = &sel->r;
942 	struct sh_vou_device *vou_dev = video_drvdata(file);
943 	struct v4l2_crop sd_crop = {.type = V4L2_BUF_TYPE_VIDEO_OUTPUT};
944 	struct v4l2_pix_format *pix = &vou_dev->pix;
945 	struct sh_vou_geometry geo;
946 	struct v4l2_subdev_format format = {
947 		.which = V4L2_SUBDEV_FORMAT_ACTIVE,
948 		/* Revisit: is this the correct code? */
949 		.format.code = MEDIA_BUS_FMT_YUYV8_2X8,
950 		.format.field = V4L2_FIELD_INTERLACED,
951 		.format.colorspace = V4L2_COLORSPACE_SMPTE170M,
952 	};
953 	unsigned int img_height_max;
954 	int ret;
955 
956 	if (sel->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
957 	    sel->target != V4L2_SEL_TGT_COMPOSE)
958 		return -EINVAL;
959 
960 	if (vb2_is_busy(&vou_dev->queue))
961 		return -EBUSY;
962 
963 	if (vou_dev->std & V4L2_STD_525_60)
964 		img_height_max = 480;
965 	else
966 		img_height_max = 576;
967 
968 	v4l_bound_align_image(&rect->width,
969 			      VOU_MIN_IMAGE_WIDTH, VOU_MAX_IMAGE_WIDTH, 1,
970 			      &rect->height,
971 			      VOU_MIN_IMAGE_HEIGHT, img_height_max, 1, 0);
972 
973 	if (rect->width + rect->left > VOU_MAX_IMAGE_WIDTH)
974 		rect->left = VOU_MAX_IMAGE_WIDTH - rect->width;
975 
976 	if (rect->height + rect->top > img_height_max)
977 		rect->top = img_height_max - rect->height;
978 
979 	geo.output = *rect;
980 	geo.in_width = pix->width;
981 	geo.in_height = pix->height;
982 
983 	/* Configure the encoder one-to-one, position at 0, ignore errors */
984 	sd_crop.c.width = geo.output.width;
985 	sd_crop.c.height = geo.output.height;
986 	/*
987 	 * We first issue a S_CROP, so that the subsequent S_FMT delivers the
988 	 * final encoder configuration.
989 	 */
990 	v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, video,
991 				   s_crop, &sd_crop);
992 	format.format.width = geo.output.width;
993 	format.format.height = geo.output.height;
994 	ret = v4l2_device_call_until_err(&vou_dev->v4l2_dev, 0, pad,
995 					 set_fmt, NULL, &format);
996 	/* Must be implemented, so, don't check for -ENOIOCTLCMD */
997 	if (ret < 0)
998 		return ret;
999 
1000 	/* Sanity checks */
1001 	if ((unsigned)format.format.width > VOU_MAX_IMAGE_WIDTH ||
1002 	    (unsigned)format.format.height > img_height_max ||
1003 	    format.format.code != MEDIA_BUS_FMT_YUYV8_2X8)
1004 		return -EIO;
1005 
1006 	geo.output.width = format.format.width;
1007 	geo.output.height = format.format.height;
1008 
1009 	/*
1010 	 * No down-scaling. According to the API, current call has precedence:
1011 	 * http://v4l2spec.bytesex.org/spec/x1904.htm#AEN1954 paragraph two.
1012 	 */
1013 	vou_adjust_input(&geo, vou_dev->std);
1014 
1015 	/* We tried to preserve output rectangle, but it could have changed */
1016 	vou_dev->rect = geo.output;
1017 	pix->width = geo.in_width;
1018 	pix->height = geo.in_height;
1019 
1020 	sh_vou_configure_geometry(vou_dev, vou_dev->pix_idx,
1021 				  geo.scale_idx_h, geo.scale_idx_v);
1022 
1023 	return 0;
1024 }
1025 
sh_vou_isr(int irq,void * dev_id)1026 static irqreturn_t sh_vou_isr(int irq, void *dev_id)
1027 {
1028 	struct sh_vou_device *vou_dev = dev_id;
1029 	static unsigned long j;
1030 	struct sh_vou_buffer *vb;
1031 	static int cnt;
1032 	u32 irq_status = sh_vou_reg_a_read(vou_dev, VOUIR), masked;
1033 	u32 vou_status = sh_vou_reg_a_read(vou_dev, VOUSTR);
1034 
1035 	if (!(irq_status & 0x300)) {
1036 		if (printk_timed_ratelimit(&j, 500))
1037 			dev_warn(vou_dev->v4l2_dev.dev, "IRQ status 0x%x!\n",
1038 				 irq_status);
1039 		return IRQ_NONE;
1040 	}
1041 
1042 	spin_lock(&vou_dev->lock);
1043 	if (!vou_dev->active || list_empty(&vou_dev->buf_list)) {
1044 		if (printk_timed_ratelimit(&j, 500))
1045 			dev_warn(vou_dev->v4l2_dev.dev,
1046 				 "IRQ without active buffer: %x!\n", irq_status);
1047 		/* Just ack: buf_release will disable further interrupts */
1048 		sh_vou_reg_a_set(vou_dev, VOUIR, 0, 0x300);
1049 		spin_unlock(&vou_dev->lock);
1050 		return IRQ_HANDLED;
1051 	}
1052 
1053 	masked = ~(0x300 & irq_status) & irq_status & 0x30304;
1054 	dev_dbg(vou_dev->v4l2_dev.dev,
1055 		"IRQ status 0x%x -> 0x%x, VOU status 0x%x, cnt %d\n",
1056 		irq_status, masked, vou_status, cnt);
1057 
1058 	cnt++;
1059 	/* side = vou_status & 0x10000; */
1060 
1061 	/* Clear only set interrupts */
1062 	sh_vou_reg_a_write(vou_dev, VOUIR, masked);
1063 
1064 	vb = vou_dev->active;
1065 	if (list_is_singular(&vb->list)) {
1066 		/* Keep cycling while no next buffer is available */
1067 		sh_vou_schedule_next(vou_dev, &vb->vb);
1068 		spin_unlock(&vou_dev->lock);
1069 		return IRQ_HANDLED;
1070 	}
1071 
1072 	list_del(&vb->list);
1073 
1074 	v4l2_get_timestamp(&vb->vb.timestamp);
1075 	vb->vb.sequence = vou_dev->sequence++;
1076 	vb->vb.field = V4L2_FIELD_INTERLACED;
1077 	vb2_buffer_done(&vb->vb.vb2_buf, VB2_BUF_STATE_DONE);
1078 
1079 	vou_dev->active = list_entry(vou_dev->buf_list.next,
1080 				     struct sh_vou_buffer, list);
1081 
1082 	if (list_is_singular(&vou_dev->buf_list)) {
1083 		/* Keep cycling while no next buffer is available */
1084 		sh_vou_schedule_next(vou_dev, &vou_dev->active->vb);
1085 	} else {
1086 		struct sh_vou_buffer *new = list_entry(vou_dev->active->list.next,
1087 						struct sh_vou_buffer, list);
1088 		sh_vou_schedule_next(vou_dev, &new->vb);
1089 	}
1090 
1091 	spin_unlock(&vou_dev->lock);
1092 
1093 	return IRQ_HANDLED;
1094 }
1095 
sh_vou_hw_init(struct sh_vou_device * vou_dev)1096 static int sh_vou_hw_init(struct sh_vou_device *vou_dev)
1097 {
1098 	struct sh_vou_pdata *pdata = vou_dev->pdata;
1099 	u32 voucr = sh_vou_ntsc_mode(pdata->bus_fmt) << 29;
1100 	int i = 100;
1101 
1102 	/* Disable all IRQs */
1103 	sh_vou_reg_a_write(vou_dev, VOUIR, 0);
1104 
1105 	/* Reset VOU interfaces - registers unaffected */
1106 	sh_vou_reg_a_write(vou_dev, VOUSRR, 0x101);
1107 	while (--i && (sh_vou_reg_a_read(vou_dev, VOUSRR) & 0x101))
1108 		udelay(1);
1109 
1110 	if (!i)
1111 		return -ETIMEDOUT;
1112 
1113 	dev_dbg(vou_dev->v4l2_dev.dev, "Reset took %dus\n", 100 - i);
1114 
1115 	if (pdata->flags & SH_VOU_PCLK_FALLING)
1116 		voucr |= 1 << 28;
1117 	if (pdata->flags & SH_VOU_HSYNC_LOW)
1118 		voucr |= 1 << 27;
1119 	if (pdata->flags & SH_VOU_VSYNC_LOW)
1120 		voucr |= 1 << 26;
1121 	sh_vou_reg_ab_set(vou_dev, VOUCR, voucr, 0xfc000000);
1122 
1123 	/* Manual register side switching at first */
1124 	sh_vou_reg_a_write(vou_dev, VOURCR, 4);
1125 	/* Default - fixed HSYNC length, can be made configurable is required */
1126 	sh_vou_reg_ab_write(vou_dev, VOUMSR, 0x800000);
1127 
1128 	sh_vou_set_fmt_vid_out(vou_dev, &vou_dev->pix);
1129 
1130 	return 0;
1131 }
1132 
1133 /* File operations */
sh_vou_open(struct file * file)1134 static int sh_vou_open(struct file *file)
1135 {
1136 	struct sh_vou_device *vou_dev = video_drvdata(file);
1137 	int err;
1138 
1139 	if (mutex_lock_interruptible(&vou_dev->fop_lock))
1140 		return -ERESTARTSYS;
1141 
1142 	err = v4l2_fh_open(file);
1143 	if (err)
1144 		goto done_open;
1145 	if (v4l2_fh_is_singular_file(file) &&
1146 	    vou_dev->status == SH_VOU_INITIALISING) {
1147 		/* First open */
1148 		pm_runtime_get_sync(vou_dev->v4l2_dev.dev);
1149 		err = sh_vou_hw_init(vou_dev);
1150 		if (err < 0) {
1151 			pm_runtime_put(vou_dev->v4l2_dev.dev);
1152 			v4l2_fh_release(file);
1153 		} else {
1154 			vou_dev->status = SH_VOU_IDLE;
1155 		}
1156 	}
1157 done_open:
1158 	mutex_unlock(&vou_dev->fop_lock);
1159 	return err;
1160 }
1161 
sh_vou_release(struct file * file)1162 static int sh_vou_release(struct file *file)
1163 {
1164 	struct sh_vou_device *vou_dev = video_drvdata(file);
1165 	bool is_last;
1166 
1167 	mutex_lock(&vou_dev->fop_lock);
1168 	is_last = v4l2_fh_is_singular_file(file);
1169 	_vb2_fop_release(file, NULL);
1170 	if (is_last) {
1171 		/* Last close */
1172 		vou_dev->status = SH_VOU_INITIALISING;
1173 		sh_vou_reg_a_set(vou_dev, VOUER, 0, 0x101);
1174 		pm_runtime_put(vou_dev->v4l2_dev.dev);
1175 	}
1176 	mutex_unlock(&vou_dev->fop_lock);
1177 	return 0;
1178 }
1179 
1180 /* sh_vou display ioctl operations */
1181 static const struct v4l2_ioctl_ops sh_vou_ioctl_ops = {
1182 	.vidioc_querycap        	= sh_vou_querycap,
1183 	.vidioc_enum_fmt_vid_out	= sh_vou_enum_fmt_vid_out,
1184 	.vidioc_g_fmt_vid_out		= sh_vou_g_fmt_vid_out,
1185 	.vidioc_s_fmt_vid_out		= sh_vou_s_fmt_vid_out,
1186 	.vidioc_try_fmt_vid_out		= sh_vou_try_fmt_vid_out,
1187 	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
1188 	.vidioc_create_bufs		= vb2_ioctl_create_bufs,
1189 	.vidioc_querybuf		= vb2_ioctl_querybuf,
1190 	.vidioc_qbuf			= vb2_ioctl_qbuf,
1191 	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
1192 	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,
1193 	.vidioc_streamon		= vb2_ioctl_streamon,
1194 	.vidioc_streamoff		= vb2_ioctl_streamoff,
1195 	.vidioc_expbuf			= vb2_ioctl_expbuf,
1196 	.vidioc_g_output		= sh_vou_g_output,
1197 	.vidioc_s_output		= sh_vou_s_output,
1198 	.vidioc_enum_output		= sh_vou_enum_output,
1199 	.vidioc_s_std			= sh_vou_s_std,
1200 	.vidioc_g_std			= sh_vou_g_std,
1201 	.vidioc_g_selection		= sh_vou_g_selection,
1202 	.vidioc_s_selection		= sh_vou_s_selection,
1203 	.vidioc_log_status		= sh_vou_log_status,
1204 };
1205 
1206 static const struct v4l2_file_operations sh_vou_fops = {
1207 	.owner		= THIS_MODULE,
1208 	.open		= sh_vou_open,
1209 	.release	= sh_vou_release,
1210 	.unlocked_ioctl	= video_ioctl2,
1211 	.mmap		= vb2_fop_mmap,
1212 	.poll		= vb2_fop_poll,
1213 	.write		= vb2_fop_write,
1214 };
1215 
1216 static const struct video_device sh_vou_video_template = {
1217 	.name		= "sh_vou",
1218 	.fops		= &sh_vou_fops,
1219 	.ioctl_ops	= &sh_vou_ioctl_ops,
1220 	.tvnorms	= V4L2_STD_525_60, /* PAL only supported in 8-bit non-bt656 mode */
1221 	.vfl_dir	= VFL_DIR_TX,
1222 };
1223 
sh_vou_probe(struct platform_device * pdev)1224 static int sh_vou_probe(struct platform_device *pdev)
1225 {
1226 	struct sh_vou_pdata *vou_pdata = pdev->dev.platform_data;
1227 	struct v4l2_rect *rect;
1228 	struct v4l2_pix_format *pix;
1229 	struct i2c_adapter *i2c_adap;
1230 	struct video_device *vdev;
1231 	struct sh_vou_device *vou_dev;
1232 	struct resource *reg_res;
1233 	struct v4l2_subdev *subdev;
1234 	struct vb2_queue *q;
1235 	int irq, ret;
1236 
1237 	reg_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1238 	irq = platform_get_irq(pdev, 0);
1239 
1240 	if (!vou_pdata || !reg_res || irq <= 0) {
1241 		dev_err(&pdev->dev, "Insufficient VOU platform information.\n");
1242 		return -ENODEV;
1243 	}
1244 
1245 	vou_dev = devm_kzalloc(&pdev->dev, sizeof(*vou_dev), GFP_KERNEL);
1246 	if (!vou_dev)
1247 		return -ENOMEM;
1248 
1249 	INIT_LIST_HEAD(&vou_dev->buf_list);
1250 	spin_lock_init(&vou_dev->lock);
1251 	mutex_init(&vou_dev->fop_lock);
1252 	vou_dev->pdata = vou_pdata;
1253 	vou_dev->status = SH_VOU_INITIALISING;
1254 	vou_dev->pix_idx = 1;
1255 
1256 	rect = &vou_dev->rect;
1257 	pix = &vou_dev->pix;
1258 
1259 	/* Fill in defaults */
1260 	vou_dev->std		= V4L2_STD_NTSC_M;
1261 	rect->left		= 0;
1262 	rect->top		= 0;
1263 	rect->width		= VOU_MAX_IMAGE_WIDTH;
1264 	rect->height		= 480;
1265 	pix->width		= VOU_MAX_IMAGE_WIDTH;
1266 	pix->height		= 480;
1267 	pix->pixelformat	= V4L2_PIX_FMT_NV16;
1268 	pix->field		= V4L2_FIELD_INTERLACED;
1269 	pix->bytesperline	= VOU_MAX_IMAGE_WIDTH;
1270 	pix->sizeimage		= VOU_MAX_IMAGE_WIDTH * 2 * 480;
1271 	pix->colorspace		= V4L2_COLORSPACE_SMPTE170M;
1272 
1273 	vou_dev->base = devm_ioremap_resource(&pdev->dev, reg_res);
1274 	if (IS_ERR(vou_dev->base))
1275 		return PTR_ERR(vou_dev->base);
1276 
1277 	ret = devm_request_irq(&pdev->dev, irq, sh_vou_isr, 0, "vou", vou_dev);
1278 	if (ret < 0)
1279 		return ret;
1280 
1281 	ret = v4l2_device_register(&pdev->dev, &vou_dev->v4l2_dev);
1282 	if (ret < 0) {
1283 		dev_err(&pdev->dev, "Error registering v4l2 device\n");
1284 		return ret;
1285 	}
1286 
1287 	vdev = &vou_dev->vdev;
1288 	*vdev = sh_vou_video_template;
1289 	if (vou_pdata->bus_fmt == SH_VOU_BUS_8BIT)
1290 		vdev->tvnorms |= V4L2_STD_PAL;
1291 	vdev->v4l2_dev = &vou_dev->v4l2_dev;
1292 	vdev->release = video_device_release_empty;
1293 	vdev->lock = &vou_dev->fop_lock;
1294 
1295 	video_set_drvdata(vdev, vou_dev);
1296 
1297 	/* Initialize the vb2 queue */
1298 	q = &vou_dev->queue;
1299 	q->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
1300 	q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_WRITE;
1301 	q->drv_priv = vou_dev;
1302 	q->buf_struct_size = sizeof(struct sh_vou_buffer);
1303 	q->ops = &sh_vou_qops;
1304 	q->mem_ops = &vb2_dma_contig_memops;
1305 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
1306 	q->min_buffers_needed = 2;
1307 	q->lock = &vou_dev->fop_lock;
1308 	ret = vb2_queue_init(q);
1309 	if (ret)
1310 		goto einitctx;
1311 
1312 	vou_dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
1313 	if (IS_ERR(vou_dev->alloc_ctx)) {
1314 		dev_err(&pdev->dev, "Can't allocate buffer context");
1315 		ret = PTR_ERR(vou_dev->alloc_ctx);
1316 		goto einitctx;
1317 	}
1318 	vdev->queue = q;
1319 	INIT_LIST_HEAD(&vou_dev->buf_list);
1320 
1321 	pm_runtime_enable(&pdev->dev);
1322 	pm_runtime_resume(&pdev->dev);
1323 
1324 	i2c_adap = i2c_get_adapter(vou_pdata->i2c_adap);
1325 	if (!i2c_adap) {
1326 		ret = -ENODEV;
1327 		goto ei2cgadap;
1328 	}
1329 
1330 	ret = sh_vou_hw_init(vou_dev);
1331 	if (ret < 0)
1332 		goto ereset;
1333 
1334 	subdev = v4l2_i2c_new_subdev_board(&vou_dev->v4l2_dev, i2c_adap,
1335 			vou_pdata->board_info, NULL);
1336 	if (!subdev) {
1337 		ret = -ENOMEM;
1338 		goto ei2cnd;
1339 	}
1340 
1341 	ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
1342 	if (ret < 0)
1343 		goto evregdev;
1344 
1345 	return 0;
1346 
1347 evregdev:
1348 ei2cnd:
1349 ereset:
1350 	i2c_put_adapter(i2c_adap);
1351 ei2cgadap:
1352 	vb2_dma_contig_cleanup_ctx(vou_dev->alloc_ctx);
1353 einitctx:
1354 	pm_runtime_disable(&pdev->dev);
1355 	v4l2_device_unregister(&vou_dev->v4l2_dev);
1356 	return ret;
1357 }
1358 
sh_vou_remove(struct platform_device * pdev)1359 static int sh_vou_remove(struct platform_device *pdev)
1360 {
1361 	struct v4l2_device *v4l2_dev = platform_get_drvdata(pdev);
1362 	struct sh_vou_device *vou_dev = container_of(v4l2_dev,
1363 						struct sh_vou_device, v4l2_dev);
1364 	struct v4l2_subdev *sd = list_entry(v4l2_dev->subdevs.next,
1365 					    struct v4l2_subdev, list);
1366 	struct i2c_client *client = v4l2_get_subdevdata(sd);
1367 
1368 	pm_runtime_disable(&pdev->dev);
1369 	video_unregister_device(&vou_dev->vdev);
1370 	i2c_put_adapter(client->adapter);
1371 	vb2_dma_contig_cleanup_ctx(vou_dev->alloc_ctx);
1372 	v4l2_device_unregister(&vou_dev->v4l2_dev);
1373 	return 0;
1374 }
1375 
1376 static struct platform_driver __refdata sh_vou = {
1377 	.remove  = sh_vou_remove,
1378 	.driver  = {
1379 		.name	= "sh-vou",
1380 	},
1381 };
1382 
1383 module_platform_driver_probe(sh_vou, sh_vou_probe);
1384 
1385 MODULE_DESCRIPTION("SuperH VOU driver");
1386 MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
1387 MODULE_LICENSE("GPL v2");
1388 MODULE_VERSION("0.1.0");
1389 MODULE_ALIAS("platform:sh-vou");
1390