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>
25 /* -----------------------------------------------------------------------------
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
)
50 /* Select SDP Read-Only Main Map */
51 ret
= sdp_write(state
, ADV748X_SDP_MAP_SEL
,
52 ADV748X_SDP_MAP_SEL_RO_MAIN
);
56 return sdp_read(state
, reg
);
59 static int adv748x_afe_status(struct adv748x_afe
*afe
, u32
*signal
,
62 struct adv748x_state
*state
= adv748x_afe_to_state(afe
);
65 /* Read status from reg 0x10 of SDP RO Map */
66 info
= adv748x_afe_read_ro_map(state
, ADV748X_SDP_RO_10
);
71 *signal
= info
& ADV748X_SDP_RO_10_IN_LOCK
?
72 0 : V4L2_IN_ST_NO_SIGNAL
;
77 /* Standard not valid if there is no signal */
78 if (!(info
& ADV748X_SDP_RO_10_IN_LOCK
)) {
79 *std
= V4L2_STD_UNKNOWN
;
83 switch (info
& 0x70) {
88 *std
= V4L2_STD_NTSC_443
;
91 *std
= V4L2_STD_PAL_M
;
94 *std
= V4L2_STD_PAL_60
;
100 *std
= V4L2_STD_SECAM
;
103 *std
= V4L2_STD_PAL_Nc
| V4L2_STD_PAL_N
;
106 *std
= V4L2_STD_SECAM
;
109 *std
= V4L2_STD_UNKNOWN
;
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
;
126 fmt
->height
= afe
->curr_norm
& V4L2_STD_525_60
? 480 : 576;
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
;
154 static void adv748x_afe_set_video_standard(struct adv748x_state
*state
,
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;
177 aspect
->numerator
= 54;
178 aspect
->denominator
= 59;
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
;
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
);
206 mutex_lock(&state
->mutex
);
208 adv748x_afe_set_video_standard(state
, afe_std
);
209 afe
->curr_norm
= std
;
211 mutex_unlock(&state
->mutex
);
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
);
223 mutex_lock(&state
->mutex
);
225 if (afe
->streaming
) {
230 /* Set auto detect mode */
231 adv748x_afe_set_video_standard(state
,
232 ADV748X_AFE_STD_AD_PAL_BG_NTSC_J_SECAM
);
236 /* Read detected standard */
237 ret
= adv748x_afe_status(afe
, NULL
, std
);
239 afe_std
= adv748x_afe_std(afe
->curr_norm
);
243 /* Restore original state */
244 adv748x_afe_set_video_standard(state
, afe_std
);
247 mutex_unlock(&state
->mutex
);
252 static int adv748x_afe_g_tvnorms(struct v4l2_subdev
*sd
, v4l2_std_id
*norm
)
254 *norm
= V4L2_STD_ALL
;
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
);
265 mutex_lock(&state
->mutex
);
267 ret
= adv748x_afe_status(afe
, status
, NULL
);
269 mutex_unlock(&state
->mutex
);
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
);
283 ret
= adv748x_afe_s_input(afe
, afe
->input
);
288 ret
= adv748x_txb_power(state
, enable
);
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");
298 adv_dbg(state
, "Couldn't detect SDP video signal\n");
301 mutex_unlock(&state
->mutex
);
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
]);
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)
343 code
->code
= MEDIA_BUS_FMT_UYVY8_2X8
;
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
)
359 if (sdformat
->which
== V4L2_SUBDEV_FORMAT_TRY
) {
360 mbusformat
= v4l2_subdev_get_try_format(sd
, cfg
, sdformat
->pad
);
361 sdformat
->format
= *mbusformat
;
363 adv748x_afe_fill_format(afe
, &sdformat
->format
);
364 adv748x_afe_propagate_pixelrate(afe
);
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
)
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
;
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 /* -----------------------------------------------------------------------------
399 static const struct v4l2_subdev_ops adv748x_afe_ops
= {
400 .video
= &adv748x_afe_video_ops
,
401 .pad
= &adv748x_afe_pad_ops
,
404 /* -----------------------------------------------------------------------------
408 static const char * const afe_ctrl_frp_menu
[] = {
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
);
425 ret
= sdp_write(state
, 0x0e, 0x00);
430 case V4L2_CID_BRIGHTNESS
:
431 ret
= sdp_write(state
, ADV748X_SDP_BRI
, ctrl
->val
);
434 /* Hue is inverted according to HSL chart */
435 ret
= sdp_write(state
, ADV748X_SDP_HUE
, -ctrl
->val
);
437 case V4L2_CID_CONTRAST
:
438 ret
= sdp_write(state
, ADV748X_SDP_CON
, ctrl
->val
);
440 case V4L2_CID_SATURATION
:
441 ret
= sdp_write(state
, ADV748X_SDP_SD_SAT_U
, ctrl
->val
);
444 ret
= sdp_write(state
, ADV748X_SDP_SD_SAT_V
, ctrl
->val
);
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
,
454 ret
= sdp_clrset(state
, ADV748X_SDP_FRP
, ADV748X_SDP_FRP_MASK
,
455 enable
? ctrl
->val
- 1 : 0);
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
);
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
]) {
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
,
541 ret
= adv748x_afe_init_controls(afe
);
548 media_entity_cleanup(&afe
->sd
.entity
);
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
);