ALSA: dice: fix kernel NULL pointer dereference due to invalid calculation for array...
[linux/fpc-iii.git] / drivers / media / i2c / adv748x / adv748x-afe.c
blob5188178588c9067d60e7a38ac08d8bd8bba08858
1 /*
2 * Driver for Analog Devices ADV748X 8 channel analog front end (AFE) receiver
3 * with standard definition processor (SDP)
5 * Copyright (C) 2017 Renesas Electronics Corp.
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation; either version 2 of the License, or (at your
10 * option) any later version.
13 #include <linux/delay.h>
14 #include <linux/module.h>
15 #include <linux/mutex.h>
16 #include <linux/v4l2-dv-timings.h>
18 #include <media/v4l2-ctrls.h>
19 #include <media/v4l2-device.h>
20 #include <media/v4l2-dv-timings.h>
21 #include <media/v4l2-ioctl.h>
23 #include "adv748x.h"
25 /* -----------------------------------------------------------------------------
26 * SDP
29 #define ADV748X_AFE_STD_AD_PAL_BG_NTSC_J_SECAM 0x0
30 #define ADV748X_AFE_STD_AD_PAL_BG_NTSC_J_SECAM_PED 0x1
31 #define ADV748X_AFE_STD_AD_PAL_N_NTSC_J_SECAM 0x2
32 #define ADV748X_AFE_STD_AD_PAL_N_NTSC_M_SECAM 0x3
33 #define ADV748X_AFE_STD_NTSC_J 0x4
34 #define ADV748X_AFE_STD_NTSC_M 0x5
35 #define ADV748X_AFE_STD_PAL60 0x6
36 #define ADV748X_AFE_STD_NTSC_443 0x7
37 #define ADV748X_AFE_STD_PAL_BG 0x8
38 #define ADV748X_AFE_STD_PAL_N 0x9
39 #define ADV748X_AFE_STD_PAL_M 0xa
40 #define ADV748X_AFE_STD_PAL_M_PED 0xb
41 #define ADV748X_AFE_STD_PAL_COMB_N 0xc
42 #define ADV748X_AFE_STD_PAL_COMB_N_PED 0xd
43 #define ADV748X_AFE_STD_PAL_SECAM 0xe
44 #define ADV748X_AFE_STD_PAL_SECAM_PED 0xf
46 static int adv748x_afe_read_ro_map(struct adv748x_state *state, u8 reg)
48 int ret;
50 /* Select SDP Read-Only Main Map */
51 ret = sdp_write(state, ADV748X_SDP_MAP_SEL,
52 ADV748X_SDP_MAP_SEL_RO_MAIN);
53 if (ret < 0)
54 return ret;
56 return sdp_read(state, reg);
59 static int adv748x_afe_status(struct adv748x_afe *afe, u32 *signal,
60 v4l2_std_id *std)
62 struct adv748x_state *state = adv748x_afe_to_state(afe);
63 int info;
65 /* Read status from reg 0x10 of SDP RO Map */
66 info = adv748x_afe_read_ro_map(state, ADV748X_SDP_RO_10);
67 if (info < 0)
68 return info;
70 if (signal)
71 *signal = info & ADV748X_SDP_RO_10_IN_LOCK ?
72 0 : V4L2_IN_ST_NO_SIGNAL;
74 if (!std)
75 return 0;
77 /* Standard not valid if there is no signal */
78 if (!(info & ADV748X_SDP_RO_10_IN_LOCK)) {
79 *std = V4L2_STD_UNKNOWN;
80 return 0;
83 switch (info & 0x70) {
84 case 0x00:
85 *std = V4L2_STD_NTSC;
86 break;
87 case 0x10:
88 *std = V4L2_STD_NTSC_443;
89 break;
90 case 0x20:
91 *std = V4L2_STD_PAL_M;
92 break;
93 case 0x30:
94 *std = V4L2_STD_PAL_60;
95 break;
96 case 0x40:
97 *std = V4L2_STD_PAL;
98 break;
99 case 0x50:
100 *std = V4L2_STD_SECAM;
101 break;
102 case 0x60:
103 *std = V4L2_STD_PAL_Nc | V4L2_STD_PAL_N;
104 break;
105 case 0x70:
106 *std = V4L2_STD_SECAM;
107 break;
108 default:
109 *std = V4L2_STD_UNKNOWN;
110 break;
113 return 0;
116 static void adv748x_afe_fill_format(struct adv748x_afe *afe,
117 struct v4l2_mbus_framefmt *fmt)
119 memset(fmt, 0, sizeof(*fmt));
121 fmt->code = MEDIA_BUS_FMT_UYVY8_2X8;
122 fmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
123 fmt->field = V4L2_FIELD_ALTERNATE;
125 fmt->width = 720;
126 fmt->height = afe->curr_norm & V4L2_STD_525_60 ? 480 : 576;
128 /* Field height */
129 fmt->height /= 2;
132 static int adv748x_afe_std(v4l2_std_id std)
134 if (std == V4L2_STD_PAL_60)
135 return ADV748X_AFE_STD_PAL60;
136 if (std == V4L2_STD_NTSC_443)
137 return ADV748X_AFE_STD_NTSC_443;
138 if (std == V4L2_STD_PAL_N)
139 return ADV748X_AFE_STD_PAL_N;
140 if (std == V4L2_STD_PAL_M)
141 return ADV748X_AFE_STD_PAL_M;
142 if (std == V4L2_STD_PAL_Nc)
143 return ADV748X_AFE_STD_PAL_COMB_N;
144 if (std & V4L2_STD_NTSC)
145 return ADV748X_AFE_STD_NTSC_M;
146 if (std & V4L2_STD_PAL)
147 return ADV748X_AFE_STD_PAL_BG;
148 if (std & V4L2_STD_SECAM)
149 return ADV748X_AFE_STD_PAL_SECAM;
151 return -EINVAL;
154 static void adv748x_afe_set_video_standard(struct adv748x_state *state,
155 int sdpstd)
157 sdp_clrset(state, ADV748X_SDP_VID_SEL, ADV748X_SDP_VID_SEL_MASK,
158 (sdpstd & 0xf) << ADV748X_SDP_VID_SEL_SHIFT);
161 static int adv748x_afe_s_input(struct adv748x_afe *afe, unsigned int input)
163 struct adv748x_state *state = adv748x_afe_to_state(afe);
165 return sdp_write(state, ADV748X_SDP_INSEL, input);
168 static int adv748x_afe_g_pixelaspect(struct v4l2_subdev *sd,
169 struct v4l2_fract *aspect)
171 struct adv748x_afe *afe = adv748x_sd_to_afe(sd);
173 if (afe->curr_norm & V4L2_STD_525_60) {
174 aspect->numerator = 11;
175 aspect->denominator = 10;
176 } else {
177 aspect->numerator = 54;
178 aspect->denominator = 59;
181 return 0;
184 /* -----------------------------------------------------------------------------
185 * v4l2_subdev_video_ops
188 static int adv748x_afe_g_std(struct v4l2_subdev *sd, v4l2_std_id *norm)
190 struct adv748x_afe *afe = adv748x_sd_to_afe(sd);
192 *norm = afe->curr_norm;
194 return 0;
197 static int adv748x_afe_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
199 struct adv748x_afe *afe = adv748x_sd_to_afe(sd);
200 struct adv748x_state *state = adv748x_afe_to_state(afe);
201 int afe_std = adv748x_afe_std(std);
203 if (afe_std < 0)
204 return afe_std;
206 mutex_lock(&state->mutex);
208 adv748x_afe_set_video_standard(state, afe_std);
209 afe->curr_norm = std;
211 mutex_unlock(&state->mutex);
213 return 0;
216 static int adv748x_afe_querystd(struct v4l2_subdev *sd, v4l2_std_id *std)
218 struct adv748x_afe *afe = adv748x_sd_to_afe(sd);
219 struct adv748x_state *state = adv748x_afe_to_state(afe);
220 int afe_std;
221 int ret;
223 mutex_lock(&state->mutex);
225 if (afe->streaming) {
226 ret = -EBUSY;
227 goto unlock;
230 /* Set auto detect mode */
231 adv748x_afe_set_video_standard(state,
232 ADV748X_AFE_STD_AD_PAL_BG_NTSC_J_SECAM);
234 msleep(100);
236 /* Read detected standard */
237 ret = adv748x_afe_status(afe, NULL, std);
239 afe_std = adv748x_afe_std(afe->curr_norm);
240 if (afe_std < 0)
241 goto unlock;
243 /* Restore original state */
244 adv748x_afe_set_video_standard(state, afe_std);
246 unlock:
247 mutex_unlock(&state->mutex);
249 return ret;
252 static int adv748x_afe_g_tvnorms(struct v4l2_subdev *sd, v4l2_std_id *norm)
254 *norm = V4L2_STD_ALL;
256 return 0;
259 static int adv748x_afe_g_input_status(struct v4l2_subdev *sd, u32 *status)
261 struct adv748x_afe *afe = adv748x_sd_to_afe(sd);
262 struct adv748x_state *state = adv748x_afe_to_state(afe);
263 int ret;
265 mutex_lock(&state->mutex);
267 ret = adv748x_afe_status(afe, status, NULL);
269 mutex_unlock(&state->mutex);
271 return ret;
274 static int adv748x_afe_s_stream(struct v4l2_subdev *sd, int enable)
276 struct adv748x_afe *afe = adv748x_sd_to_afe(sd);
277 struct adv748x_state *state = adv748x_afe_to_state(afe);
278 int ret, signal = V4L2_IN_ST_NO_SIGNAL;
280 mutex_lock(&state->mutex);
282 if (enable) {
283 ret = adv748x_afe_s_input(afe, afe->input);
284 if (ret)
285 goto unlock;
288 ret = adv748x_txb_power(state, enable);
289 if (ret)
290 goto unlock;
292 afe->streaming = enable;
294 adv748x_afe_status(afe, &signal, NULL);
295 if (signal != V4L2_IN_ST_NO_SIGNAL)
296 adv_dbg(state, "Detected SDP signal\n");
297 else
298 adv_dbg(state, "Couldn't detect SDP video signal\n");
300 unlock:
301 mutex_unlock(&state->mutex);
303 return ret;
306 static const struct v4l2_subdev_video_ops adv748x_afe_video_ops = {
307 .g_std = adv748x_afe_g_std,
308 .s_std = adv748x_afe_s_std,
309 .querystd = adv748x_afe_querystd,
310 .g_tvnorms = adv748x_afe_g_tvnorms,
311 .g_input_status = adv748x_afe_g_input_status,
312 .s_stream = adv748x_afe_s_stream,
313 .g_pixelaspect = adv748x_afe_g_pixelaspect,
316 /* -----------------------------------------------------------------------------
317 * v4l2_subdev_pad_ops
320 static int adv748x_afe_propagate_pixelrate(struct adv748x_afe *afe)
322 struct v4l2_subdev *tx;
323 unsigned int width, height, fps;
325 tx = adv748x_get_remote_sd(&afe->pads[ADV748X_AFE_SOURCE]);
326 if (!tx)
327 return -ENOLINK;
329 width = 720;
330 height = afe->curr_norm & V4L2_STD_525_60 ? 480 : 576;
331 fps = afe->curr_norm & V4L2_STD_525_60 ? 30 : 25;
333 return adv748x_csi2_set_pixelrate(tx, width * height * fps);
336 static int adv748x_afe_enum_mbus_code(struct v4l2_subdev *sd,
337 struct v4l2_subdev_pad_config *cfg,
338 struct v4l2_subdev_mbus_code_enum *code)
340 if (code->index != 0)
341 return -EINVAL;
343 code->code = MEDIA_BUS_FMT_UYVY8_2X8;
345 return 0;
348 static int adv748x_afe_get_format(struct v4l2_subdev *sd,
349 struct v4l2_subdev_pad_config *cfg,
350 struct v4l2_subdev_format *sdformat)
352 struct adv748x_afe *afe = adv748x_sd_to_afe(sd);
353 struct v4l2_mbus_framefmt *mbusformat;
355 /* It makes no sense to get the format of the analog sink pads */
356 if (sdformat->pad != ADV748X_AFE_SOURCE)
357 return -EINVAL;
359 if (sdformat->which == V4L2_SUBDEV_FORMAT_TRY) {
360 mbusformat = v4l2_subdev_get_try_format(sd, cfg, sdformat->pad);
361 sdformat->format = *mbusformat;
362 } else {
363 adv748x_afe_fill_format(afe, &sdformat->format);
364 adv748x_afe_propagate_pixelrate(afe);
367 return 0;
370 static int adv748x_afe_set_format(struct v4l2_subdev *sd,
371 struct v4l2_subdev_pad_config *cfg,
372 struct v4l2_subdev_format *sdformat)
374 struct v4l2_mbus_framefmt *mbusformat;
376 /* It makes no sense to get the format of the analog sink pads */
377 if (sdformat->pad != ADV748X_AFE_SOURCE)
378 return -EINVAL;
380 if (sdformat->which == V4L2_SUBDEV_FORMAT_ACTIVE)
381 return adv748x_afe_get_format(sd, cfg, sdformat);
383 mbusformat = v4l2_subdev_get_try_format(sd, cfg, sdformat->pad);
384 *mbusformat = sdformat->format;
386 return 0;
389 static const struct v4l2_subdev_pad_ops adv748x_afe_pad_ops = {
390 .enum_mbus_code = adv748x_afe_enum_mbus_code,
391 .set_fmt = adv748x_afe_set_format,
392 .get_fmt = adv748x_afe_get_format,
395 /* -----------------------------------------------------------------------------
396 * v4l2_subdev_ops
399 static const struct v4l2_subdev_ops adv748x_afe_ops = {
400 .video = &adv748x_afe_video_ops,
401 .pad = &adv748x_afe_pad_ops,
404 /* -----------------------------------------------------------------------------
405 * Controls
408 static const char * const afe_ctrl_frp_menu[] = {
409 "Disabled",
410 "Solid Blue",
411 "Color Bars",
412 "Grey Ramp",
413 "Cb Ramp",
414 "Cr Ramp",
415 "Boundary"
418 static int adv748x_afe_s_ctrl(struct v4l2_ctrl *ctrl)
420 struct adv748x_afe *afe = adv748x_ctrl_to_afe(ctrl);
421 struct adv748x_state *state = adv748x_afe_to_state(afe);
422 bool enable;
423 int ret;
425 ret = sdp_write(state, 0x0e, 0x00);
426 if (ret < 0)
427 return ret;
429 switch (ctrl->id) {
430 case V4L2_CID_BRIGHTNESS:
431 ret = sdp_write(state, ADV748X_SDP_BRI, ctrl->val);
432 break;
433 case V4L2_CID_HUE:
434 /* Hue is inverted according to HSL chart */
435 ret = sdp_write(state, ADV748X_SDP_HUE, -ctrl->val);
436 break;
437 case V4L2_CID_CONTRAST:
438 ret = sdp_write(state, ADV748X_SDP_CON, ctrl->val);
439 break;
440 case V4L2_CID_SATURATION:
441 ret = sdp_write(state, ADV748X_SDP_SD_SAT_U, ctrl->val);
442 if (ret)
443 break;
444 ret = sdp_write(state, ADV748X_SDP_SD_SAT_V, ctrl->val);
445 break;
446 case V4L2_CID_TEST_PATTERN:
447 enable = !!ctrl->val;
449 /* Enable/Disable Color bar test patterns */
450 ret = sdp_clrset(state, ADV748X_SDP_DEF, ADV748X_SDP_DEF_VAL_EN,
451 enable);
452 if (ret)
453 break;
454 ret = sdp_clrset(state, ADV748X_SDP_FRP, ADV748X_SDP_FRP_MASK,
455 enable ? ctrl->val - 1 : 0);
456 break;
457 default:
458 return -EINVAL;
461 return ret;
464 static const struct v4l2_ctrl_ops adv748x_afe_ctrl_ops = {
465 .s_ctrl = adv748x_afe_s_ctrl,
468 static int adv748x_afe_init_controls(struct adv748x_afe *afe)
470 struct adv748x_state *state = adv748x_afe_to_state(afe);
472 v4l2_ctrl_handler_init(&afe->ctrl_hdl, 5);
474 /* Use our mutex for the controls */
475 afe->ctrl_hdl.lock = &state->mutex;
477 v4l2_ctrl_new_std(&afe->ctrl_hdl, &adv748x_afe_ctrl_ops,
478 V4L2_CID_BRIGHTNESS, ADV748X_SDP_BRI_MIN,
479 ADV748X_SDP_BRI_MAX, 1, ADV748X_SDP_BRI_DEF);
480 v4l2_ctrl_new_std(&afe->ctrl_hdl, &adv748x_afe_ctrl_ops,
481 V4L2_CID_CONTRAST, ADV748X_SDP_CON_MIN,
482 ADV748X_SDP_CON_MAX, 1, ADV748X_SDP_CON_DEF);
483 v4l2_ctrl_new_std(&afe->ctrl_hdl, &adv748x_afe_ctrl_ops,
484 V4L2_CID_SATURATION, ADV748X_SDP_SAT_MIN,
485 ADV748X_SDP_SAT_MAX, 1, ADV748X_SDP_SAT_DEF);
486 v4l2_ctrl_new_std(&afe->ctrl_hdl, &adv748x_afe_ctrl_ops,
487 V4L2_CID_HUE, ADV748X_SDP_HUE_MIN,
488 ADV748X_SDP_HUE_MAX, 1, ADV748X_SDP_HUE_DEF);
490 v4l2_ctrl_new_std_menu_items(&afe->ctrl_hdl, &adv748x_afe_ctrl_ops,
491 V4L2_CID_TEST_PATTERN,
492 ARRAY_SIZE(afe_ctrl_frp_menu) - 1,
493 0, 0, afe_ctrl_frp_menu);
495 afe->sd.ctrl_handler = &afe->ctrl_hdl;
496 if (afe->ctrl_hdl.error) {
497 v4l2_ctrl_handler_free(&afe->ctrl_hdl);
498 return afe->ctrl_hdl.error;
501 return v4l2_ctrl_handler_setup(&afe->ctrl_hdl);
504 int adv748x_afe_init(struct adv748x_afe *afe)
506 struct adv748x_state *state = adv748x_afe_to_state(afe);
507 int ret;
508 unsigned int i;
510 afe->input = 0;
511 afe->streaming = false;
512 afe->curr_norm = V4L2_STD_NTSC_M;
514 adv748x_subdev_init(&afe->sd, state, &adv748x_afe_ops,
515 MEDIA_ENT_F_ATV_DECODER, "afe");
517 /* Identify the first connector found as a default input if set */
518 for (i = ADV748X_PORT_AIN0; i <= ADV748X_PORT_AIN7; i++) {
519 /* Inputs and ports are 1-indexed to match the data sheet */
520 if (state->endpoints[i]) {
521 afe->input = i;
522 break;
526 adv748x_afe_s_input(afe, afe->input);
528 adv_dbg(state, "AFE Default input set to %d\n", afe->input);
530 /* Entity pads and sinks are 0-indexed to match the pads */
531 for (i = ADV748X_AFE_SINK_AIN0; i <= ADV748X_AFE_SINK_AIN7; i++)
532 afe->pads[i].flags = MEDIA_PAD_FL_SINK;
534 afe->pads[ADV748X_AFE_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
536 ret = media_entity_pads_init(&afe->sd.entity, ADV748X_AFE_NR_PADS,
537 afe->pads);
538 if (ret)
539 return ret;
541 ret = adv748x_afe_init_controls(afe);
542 if (ret)
543 goto error;
545 return 0;
547 error:
548 media_entity_cleanup(&afe->sd.entity);
550 return ret;
553 void adv748x_afe_cleanup(struct adv748x_afe *afe)
555 v4l2_device_unregister_subdev(&afe->sd);
556 media_entity_cleanup(&afe->sd.entity);
557 v4l2_ctrl_handler_free(&afe->ctrl_hdl);