@@ -56,6 +56,28 @@ MODULE_LICENSE("GPL");
5656/* ADV7842 system clock frequency */
5757#define ADV7842_fsc (28636360)
5858
59+ #define ADV7842_RGB_OUT (1 << 1)
60+
61+ #define ADV7842_OP_FORMAT_SEL_8BIT (0 << 0)
62+ #define ADV7842_OP_FORMAT_SEL_10BIT (1 << 0)
63+ #define ADV7842_OP_FORMAT_SEL_12BIT (2 << 0)
64+
65+ #define ADV7842_OP_MODE_SEL_SDR_422 (0 << 5)
66+ #define ADV7842_OP_MODE_SEL_DDR_422 (1 << 5)
67+ #define ADV7842_OP_MODE_SEL_SDR_444 (2 << 5)
68+ #define ADV7842_OP_MODE_SEL_DDR_444 (3 << 5)
69+ #define ADV7842_OP_MODE_SEL_SDR_422_2X (4 << 5)
70+ #define ADV7842_OP_MODE_SEL_ADI_CM (5 << 5)
71+
72+ #define ADV7842_OP_CH_SEL_GBR (0 << 5)
73+ #define ADV7842_OP_CH_SEL_GRB (1 << 5)
74+ #define ADV7842_OP_CH_SEL_BGR (2 << 5)
75+ #define ADV7842_OP_CH_SEL_RGB (3 << 5)
76+ #define ADV7842_OP_CH_SEL_BRG (4 << 5)
77+ #define ADV7842_OP_CH_SEL_RBG (5 << 5)
78+
79+ #define ADV7842_OP_SWAP_CB_CR (1 << 0)
80+
5981/*
6082**********************************************************************
6183*
@@ -64,6 +86,14 @@ MODULE_LICENSE("GPL");
6486**********************************************************************
6587*/
6688
89+ struct adv7842_format_info {
90+ u32 code ;
91+ u8 op_ch_sel ;
92+ bool rgb_out ;
93+ bool swap_cb_cr ;
94+ u8 op_format_sel ;
95+ };
96+
6797struct adv7842_state {
6898 struct adv7842_platform_data pdata ;
6999 struct v4l2_subdev sd ;
@@ -72,6 +102,9 @@ struct adv7842_state {
72102 enum adv7842_mode mode ;
73103 struct v4l2_dv_timings timings ;
74104 enum adv7842_vid_std_select vid_std_select ;
105+
106+ const struct adv7842_format_info * format ;
107+
75108 v4l2_std_id norm ;
76109 struct {
77110 u8 edid [256 ];
@@ -221,11 +254,21 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
221254 return & container_of (ctrl -> handler , struct adv7842_state , hdl )-> sd ;
222255}
223256
257+ static inline unsigned hblanking (const struct v4l2_bt_timings * t )
258+ {
259+ return V4L2_DV_BT_BLANKING_WIDTH (t );
260+ }
261+
224262static inline unsigned htotal (const struct v4l2_bt_timings * t )
225263{
226264 return V4L2_DV_BT_FRAME_WIDTH (t );
227265}
228266
267+ static inline unsigned vblanking (const struct v4l2_bt_timings * t )
268+ {
269+ return V4L2_DV_BT_BLANKING_HEIGHT (t );
270+ }
271+
229272static inline unsigned vtotal (const struct v4l2_bt_timings * t )
230273{
231274 return V4L2_DV_BT_FRAME_HEIGHT (t );
@@ -335,6 +378,12 @@ static inline int io_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 va
335378 return io_write (sd , reg , (io_read (sd , reg ) & mask ) | val );
336379}
337380
381+ static inline int io_write_clr_set (struct v4l2_subdev * sd ,
382+ u8 reg , u8 mask , u8 val )
383+ {
384+ return io_write (sd , reg , (io_read (sd , reg ) & ~mask ) | val );
385+ }
386+
338387static inline int avlink_read (struct v4l2_subdev * sd , u8 reg )
339388{
340389 struct adv7842_state * state = to_state (sd );
@@ -535,6 +584,64 @@ static void main_reset(struct v4l2_subdev *sd)
535584 mdelay (5 );
536585}
537586
587+ /* -----------------------------------------------------------------------------
588+ * Format helpers
589+ */
590+
591+ static const struct adv7842_format_info adv7842_formats [] = {
592+ { MEDIA_BUS_FMT_RGB888_1X24 , ADV7842_OP_CH_SEL_RGB , true, false,
593+ ADV7842_OP_MODE_SEL_SDR_444 | ADV7842_OP_FORMAT_SEL_8BIT },
594+ { MEDIA_BUS_FMT_YUYV8_2X8 , ADV7842_OP_CH_SEL_RGB , false, false,
595+ ADV7842_OP_MODE_SEL_SDR_422 | ADV7842_OP_FORMAT_SEL_8BIT },
596+ { MEDIA_BUS_FMT_YVYU8_2X8 , ADV7842_OP_CH_SEL_RGB , false, true,
597+ ADV7842_OP_MODE_SEL_SDR_422 | ADV7842_OP_FORMAT_SEL_8BIT },
598+ { MEDIA_BUS_FMT_YUYV10_2X10 , ADV7842_OP_CH_SEL_RGB , false, false,
599+ ADV7842_OP_MODE_SEL_SDR_422 | ADV7842_OP_FORMAT_SEL_10BIT },
600+ { MEDIA_BUS_FMT_YVYU10_2X10 , ADV7842_OP_CH_SEL_RGB , false, true,
601+ ADV7842_OP_MODE_SEL_SDR_422 | ADV7842_OP_FORMAT_SEL_10BIT },
602+ { MEDIA_BUS_FMT_YUYV12_2X12 , ADV7842_OP_CH_SEL_RGB , false, false,
603+ ADV7842_OP_MODE_SEL_SDR_422 | ADV7842_OP_FORMAT_SEL_12BIT },
604+ { MEDIA_BUS_FMT_YVYU12_2X12 , ADV7842_OP_CH_SEL_RGB , false, true,
605+ ADV7842_OP_MODE_SEL_SDR_422 | ADV7842_OP_FORMAT_SEL_12BIT },
606+ { MEDIA_BUS_FMT_UYVY8_1X16 , ADV7842_OP_CH_SEL_RBG , false, false,
607+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_8BIT },
608+ { MEDIA_BUS_FMT_VYUY8_1X16 , ADV7842_OP_CH_SEL_RBG , false, true,
609+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_8BIT },
610+ { MEDIA_BUS_FMT_YUYV8_1X16 , ADV7842_OP_CH_SEL_RGB , false, false,
611+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_8BIT },
612+ { MEDIA_BUS_FMT_YVYU8_1X16 , ADV7842_OP_CH_SEL_RGB , false, true,
613+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_8BIT },
614+ { MEDIA_BUS_FMT_UYVY10_1X20 , ADV7842_OP_CH_SEL_RBG , false, false,
615+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_10BIT },
616+ { MEDIA_BUS_FMT_VYUY10_1X20 , ADV7842_OP_CH_SEL_RBG , false, true,
617+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_10BIT },
618+ { MEDIA_BUS_FMT_YUYV10_1X20 , ADV7842_OP_CH_SEL_RGB , false, false,
619+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_10BIT },
620+ { MEDIA_BUS_FMT_YVYU10_1X20 , ADV7842_OP_CH_SEL_RGB , false, true,
621+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_10BIT },
622+ { MEDIA_BUS_FMT_UYVY12_1X24 , ADV7842_OP_CH_SEL_RBG , false, false,
623+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_12BIT },
624+ { MEDIA_BUS_FMT_VYUY12_1X24 , ADV7842_OP_CH_SEL_RBG , false, true,
625+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_12BIT },
626+ { MEDIA_BUS_FMT_YUYV12_1X24 , ADV7842_OP_CH_SEL_RGB , false, false,
627+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_12BIT },
628+ { MEDIA_BUS_FMT_YVYU12_1X24 , ADV7842_OP_CH_SEL_RGB , false, true,
629+ ADV7842_OP_MODE_SEL_SDR_422_2X | ADV7842_OP_FORMAT_SEL_12BIT },
630+ };
631+
632+ static const struct adv7842_format_info *
633+ adv7842_format_info (struct adv7842_state * state , u32 code )
634+ {
635+ unsigned int i ;
636+
637+ for (i = 0 ; i < ARRAY_SIZE (adv7842_formats ); ++ i ) {
638+ if (adv7842_formats [i ].code == code )
639+ return & adv7842_formats [i ];
640+ }
641+
642+ return NULL ;
643+ }
644+
538645/* ----------------------------------------------------------------------- */
539646
540647static inline bool is_analog_input (struct v4l2_subdev * sd )
@@ -1440,6 +1547,8 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd,
14401547 }
14411548 bt -> interlaced = stdi .interlaced ?
14421549 V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE ;
1550+ bt -> standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
1551+ V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT ;
14431552
14441553 if (is_digital_input (sd )) {
14451554 uint32_t freq ;
@@ -1478,6 +1587,10 @@ static int adv7842_query_dv_timings(struct v4l2_subdev *sd,
14781587 hdmi_read (sd , 0x31 )) / 2 ;
14791588 bt -> il_vbackporch = ((hdmi_read (sd , 0x34 ) & 0x1f ) * 256 +
14801589 hdmi_read (sd , 0x35 )) / 2 ;
1590+ } else {
1591+ bt -> il_vfrontporch = 0 ;
1592+ bt -> il_vsync = 0 ;
1593+ bt -> il_vbackporch = 0 ;
14811594 }
14821595 adv7842_fill_optional_dv_timings_fields (sd , timings );
14831596 } else {
@@ -1871,47 +1984,145 @@ static int adv7842_enum_mbus_code(struct v4l2_subdev *sd,
18711984 struct v4l2_subdev_pad_config * cfg ,
18721985 struct v4l2_subdev_mbus_code_enum * code )
18731986{
1874- if (code -> pad || code -> index )
1987+ if (code -> index >= ARRAY_SIZE ( adv7842_formats ) )
18751988 return - EINVAL ;
1876- /* Good enough for now */
1877- code -> code = MEDIA_BUS_FMT_FIXED ;
1989+ code -> code = adv7842_formats [code -> index ].code ;
18781990 return 0 ;
18791991}
18801992
1881- static int adv7842_fill_fmt (struct v4l2_subdev * sd ,
1882- struct v4l2_subdev_pad_config * cfg ,
1883- struct v4l2_subdev_format * format )
1993+ static void adv7842_fill_format (struct adv7842_state * state ,
1994+ struct v4l2_mbus_framefmt * format )
1995+ {
1996+ memset (format , 0 , sizeof (* format ));
1997+
1998+ format -> width = state -> timings .bt .width ;
1999+ format -> height = state -> timings .bt .height ;
2000+ format -> field = V4L2_FIELD_NONE ;
2001+ format -> colorspace = V4L2_COLORSPACE_SRGB ;
2002+
2003+ if (state -> timings .bt .flags & V4L2_DV_FL_IS_CE_VIDEO )
2004+ format -> colorspace = (state -> timings .bt .height <= 576 ) ?
2005+ V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709 ;
2006+ }
2007+
2008+ /*
2009+ * Compute the op_ch_sel value required to obtain on the bus the component order
2010+ * corresponding to the selected format taking into account bus reordering
2011+ * applied by the board at the output of the device.
2012+ *
2013+ * The following table gives the op_ch_value from the format component order
2014+ * (expressed as op_ch_sel value in column) and the bus reordering (expressed as
2015+ * adv7842_bus_order value in row).
2016+ *
2017+ * | GBR(0) GRB(1) BGR(2) RGB(3) BRG(4) RBG(5)
2018+ * ----------+-------------------------------------------------
2019+ * RGB (NOP) | GBR GRB BGR RGB BRG RBG
2020+ * GRB (1-2) | BGR RGB GBR GRB RBG BRG
2021+ * RBG (2-3) | GRB GBR BRG RBG BGR RGB
2022+ * BGR (1-3) | RBG BRG RGB BGR GRB GBR
2023+ * BRG (ROR) | BRG RBG GRB GBR RGB BGR
2024+ * GBR (ROL) | RGB BGR RBG BRG GBR GRB
2025+ */
2026+ static unsigned int adv7842_op_ch_sel (struct adv7842_state * state )
2027+ {
2028+ #define _SEL (a , b , c , d , e , f ) { \
2029+ ADV7842_OP_CH_SEL_##a, ADV7842_OP_CH_SEL_##b, ADV7842_OP_CH_SEL_##c, \
2030+ ADV7842_OP_CH_SEL_##d, ADV7842_OP_CH_SEL_##e, ADV7842_OP_CH_SEL_##f }
2031+ #define _BUS (x ) [ADV7842_BUS_ORDER_##x]
2032+
2033+ static const unsigned int op_ch_sel [6 ][6 ] = {
2034+ _BUS (RGB ) /* NOP */ = _SEL (GBR , GRB , BGR , RGB , BRG , RBG ),
2035+ _BUS (GRB ) /* 1-2 */ = _SEL (BGR , RGB , GBR , GRB , RBG , BRG ),
2036+ _BUS (RBG ) /* 2-3 */ = _SEL (GRB , GBR , BRG , RBG , BGR , RGB ),
2037+ _BUS (BGR ) /* 1-3 */ = _SEL (RBG , BRG , RGB , BGR , GRB , GBR ),
2038+ _BUS (BRG ) /* ROR */ = _SEL (BRG , RBG , GRB , GBR , RGB , BGR ),
2039+ _BUS (GBR ) /* ROL */ = _SEL (RGB , BGR , RBG , BRG , GBR , GRB ),
2040+ };
2041+
2042+ return op_ch_sel [state -> pdata .bus_order ][state -> format -> op_ch_sel >> 5 ];
2043+ }
2044+
2045+ static void adv7842_setup_format (struct adv7842_state * state )
2046+ {
2047+ struct v4l2_subdev * sd = & state -> sd ;
2048+
2049+ io_write_clr_set (sd , 0x02 , 0x02 ,
2050+ state -> format -> rgb_out ? ADV7842_RGB_OUT : 0 );
2051+ io_write (sd , 0x03 , state -> format -> op_format_sel |
2052+ state -> pdata .op_format_mode_sel );
2053+ io_write_clr_set (sd , 0x04 , 0xe0 , adv7842_op_ch_sel (state ));
2054+ io_write_clr_set (sd , 0x05 , 0x01 ,
2055+ state -> format -> swap_cb_cr ? ADV7842_OP_SWAP_CB_CR : 0 );
2056+ }
2057+
2058+ static int adv7842_get_format (struct v4l2_subdev * sd ,
2059+ struct v4l2_subdev_pad_config * cfg ,
2060+ struct v4l2_subdev_format * format )
18842061{
1885- struct v4l2_mbus_framefmt * fmt = & format -> format ;
18862062 struct adv7842_state * state = to_state (sd );
18872063
1888- if (format -> pad )
2064+ if (format -> pad != ADV7842_PAD_SOURCE )
18892065 return - EINVAL ;
18902066
1891- fmt -> width = state -> timings .bt .width ;
1892- fmt -> height = state -> timings .bt .height ;
1893- fmt -> code = MEDIA_BUS_FMT_FIXED ;
1894- fmt -> field = V4L2_FIELD_NONE ;
1895-
18962067 if (state -> mode == ADV7842_MODE_SDP ) {
18972068 /* SPD block */
1898- if (!(sdp_read (sd , 0x5A ) & 0x01 ))
2069+ if (!(sdp_read (sd , 0x5a ) & 0x01 ))
18992070 return - EINVAL ;
1900- fmt -> width = 720 ;
2071+ format -> format .code = MEDIA_BUS_FMT_YUYV8_2X8 ;
2072+ format -> format .width = 720 ;
19012073 /* valid signal */
19022074 if (state -> norm & V4L2_STD_525_60 )
1903- fmt -> height = 480 ;
2075+ format -> format . height = 480 ;
19042076 else
1905- fmt -> height = 576 ;
1906- fmt -> colorspace = V4L2_COLORSPACE_SMPTE170M ;
2077+ format -> format . height = 576 ;
2078+ format -> format . colorspace = V4L2_COLORSPACE_SMPTE170M ;
19072079 return 0 ;
19082080 }
19092081
1910- fmt -> colorspace = V4L2_COLORSPACE_SRGB ;
1911- if (state -> timings .bt .flags & V4L2_DV_FL_IS_CE_VIDEO ) {
1912- fmt -> colorspace = (state -> timings .bt .height <= 576 ) ?
1913- V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709 ;
2082+ adv7842_fill_format (state , & format -> format );
2083+
2084+ if (format -> which == V4L2_SUBDEV_FORMAT_TRY ) {
2085+ struct v4l2_mbus_framefmt * fmt ;
2086+
2087+ fmt = v4l2_subdev_get_try_format (sd , cfg , format -> pad );
2088+ format -> format .code = fmt -> code ;
2089+ } else {
2090+ format -> format .code = state -> format -> code ;
19142091 }
2092+
2093+ return 0 ;
2094+ }
2095+
2096+ static int adv7842_set_format (struct v4l2_subdev * sd ,
2097+ struct v4l2_subdev_pad_config * cfg ,
2098+ struct v4l2_subdev_format * format )
2099+ {
2100+ struct adv7842_state * state = to_state (sd );
2101+ const struct adv7842_format_info * info ;
2102+
2103+ if (format -> pad != ADV7842_PAD_SOURCE )
2104+ return - EINVAL ;
2105+
2106+ if (state -> mode == ADV7842_MODE_SDP )
2107+ return adv7842_get_format (sd , cfg , format );
2108+
2109+ info = adv7842_format_info (state , format -> format .code );
2110+ if (info == NULL )
2111+ info = adv7842_format_info (state , MEDIA_BUS_FMT_YUYV8_2X8 );
2112+
2113+ adv7842_fill_format (state , & format -> format );
2114+ format -> format .code = info -> code ;
2115+
2116+ if (format -> which == V4L2_SUBDEV_FORMAT_TRY ) {
2117+ struct v4l2_mbus_framefmt * fmt ;
2118+
2119+ fmt = v4l2_subdev_get_try_format (sd , cfg , format -> pad );
2120+ fmt -> code = format -> format .code ;
2121+ } else {
2122+ state -> format = info ;
2123+ adv7842_setup_format (state );
2124+ }
2125+
19152126 return 0 ;
19162127}
19172128
@@ -2551,14 +2762,11 @@ static int adv7842_core_init(struct v4l2_subdev *sd)
25512762 0xf0 |
25522763 pdata -> alt_gamma << 3 |
25532764 pdata -> op_656_range << 2 |
2554- pdata -> rgb_out << 1 |
25552765 pdata -> alt_data_sat << 0 );
2556- io_write (sd , 0x03 , pdata -> op_format_sel );
2557- io_write_and_or (sd , 0x04 , 0x1f , pdata -> op_ch_sel << 5 );
25582766 io_write_and_or (sd , 0x05 , 0xf0 , pdata -> blank_data << 3 |
25592767 pdata -> insert_av_codes << 2 |
2560- pdata -> replicate_av_codes << 1 |
2561- pdata -> invert_cbcr << 0 );
2768+ pdata -> replicate_av_codes << 1 );
2769+ adv7842_setup_format ( state );
25622770
25632771 /* HDMI audio */
25642772 hdmi_write_and_or (sd , 0x1a , 0xf1 , 0x08 ); /* Wait 1 s before unmute */
@@ -2818,13 +3026,13 @@ static const struct v4l2_subdev_video_ops adv7842_video_ops = {
28183026};
28193027
28203028static const struct v4l2_subdev_pad_ops adv7842_pad_ops = {
3029+ .enum_mbus_code = adv7842_enum_mbus_code ,
3030+ .get_fmt = adv7842_get_format ,
3031+ .set_fmt = adv7842_set_format ,
28213032 .get_edid = adv7842_get_edid ,
28223033 .set_edid = adv7842_set_edid ,
28233034 .enum_dv_timings = adv7842_enum_dv_timings ,
28243035 .dv_timings_cap = adv7842_dv_timings_cap ,
2825- .enum_mbus_code = adv7842_enum_mbus_code ,
2826- .get_fmt = adv7842_fill_fmt ,
2827- .set_fmt = adv7842_fill_fmt ,
28283036};
28293037
28303038static const struct v4l2_subdev_ops adv7842_ops = {
@@ -2991,6 +3199,7 @@ static int adv7842_probe(struct i2c_client *client,
29913199 /* platform data */
29923200 state -> pdata = * pdata ;
29933201 state -> timings = cea640x480 ;
3202+ state -> format = adv7842_format_info (state , MEDIA_BUS_FMT_YUYV8_2X8 );
29943203
29953204 sd = & state -> sd ;
29963205 v4l2_i2c_subdev_init (sd , client , & adv7842_ops );
0 commit comments