diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2014-01-29 08:08:58 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <m.chehab@samsung.com> | 2014-05-25 11:56:15 -0400 |
commit | c784b1e2ece8a591263050d1f59607547dfad8f3 (patch) | |
tree | 718f6d67e21d1b7d6e739bae9652080428a93621 /drivers/media/i2c | |
parent | 454378923a9b44e26918893fac8bdeb43ae0f57b (diff) |
[media] adv7604: Add sink pads
The ADV7604 has sink pads for its HDMI and analog inputs. Report them.
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
Diffstat (limited to 'drivers/media/i2c')
-rw-r--r-- | drivers/media/i2c/adv7604.c | 61 |
1 files changed, 35 insertions, 26 deletions
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index ca7590641581..79fb34d5ee2d 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c | |||
@@ -97,13 +97,15 @@ struct adv7604_chip_info { | |||
97 | * | 97 | * |
98 | ********************************************************************** | 98 | ********************************************************************** |
99 | */ | 99 | */ |
100 | |||
100 | struct adv7604_state { | 101 | struct adv7604_state { |
101 | const struct adv7604_chip_info *info; | 102 | const struct adv7604_chip_info *info; |
102 | struct adv7604_platform_data pdata; | 103 | struct adv7604_platform_data pdata; |
103 | struct v4l2_subdev sd; | 104 | struct v4l2_subdev sd; |
104 | struct media_pad pad; | 105 | struct media_pad pads[ADV7604_PAD_MAX]; |
106 | unsigned int source_pad; | ||
105 | struct v4l2_ctrl_handler hdl; | 107 | struct v4l2_ctrl_handler hdl; |
106 | enum adv7604_input_port selected_input; | 108 | enum adv7604_pad selected_input; |
107 | struct v4l2_dv_timings timings; | 109 | struct v4l2_dv_timings timings; |
108 | struct { | 110 | struct { |
109 | u8 edid[256]; | 111 | u8 edid[256]; |
@@ -775,18 +777,18 @@ static inline bool is_analog_input(struct v4l2_subdev *sd) | |||
775 | { | 777 | { |
776 | struct adv7604_state *state = to_state(sd); | 778 | struct adv7604_state *state = to_state(sd); |
777 | 779 | ||
778 | return state->selected_input == ADV7604_INPUT_VGA_RGB || | 780 | return state->selected_input == ADV7604_PAD_VGA_RGB || |
779 | state->selected_input == ADV7604_INPUT_VGA_COMP; | 781 | state->selected_input == ADV7604_PAD_VGA_COMP; |
780 | } | 782 | } |
781 | 783 | ||
782 | static inline bool is_digital_input(struct v4l2_subdev *sd) | 784 | static inline bool is_digital_input(struct v4l2_subdev *sd) |
783 | { | 785 | { |
784 | struct adv7604_state *state = to_state(sd); | 786 | struct adv7604_state *state = to_state(sd); |
785 | 787 | ||
786 | return state->selected_input == ADV7604_INPUT_HDMI_PORT_A || | 788 | return state->selected_input == ADV7604_PAD_HDMI_PORT_A || |
787 | state->selected_input == ADV7604_INPUT_HDMI_PORT_B || | 789 | state->selected_input == ADV7604_PAD_HDMI_PORT_B || |
788 | state->selected_input == ADV7604_INPUT_HDMI_PORT_C || | 790 | state->selected_input == ADV7604_PAD_HDMI_PORT_C || |
789 | state->selected_input == ADV7604_INPUT_HDMI_PORT_D; | 791 | state->selected_input == ADV7604_PAD_HDMI_PORT_D; |
790 | } | 792 | } |
791 | 793 | ||
792 | /* ----------------------------------------------------------------------- */ | 794 | /* ----------------------------------------------------------------------- */ |
@@ -1066,14 +1068,14 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd) | |||
1066 | 1068 | ||
1067 | switch (state->rgb_quantization_range) { | 1069 | switch (state->rgb_quantization_range) { |
1068 | case V4L2_DV_RGB_RANGE_AUTO: | 1070 | case V4L2_DV_RGB_RANGE_AUTO: |
1069 | if (state->selected_input == ADV7604_INPUT_VGA_RGB) { | 1071 | if (state->selected_input == ADV7604_PAD_VGA_RGB) { |
1070 | /* Receiving analog RGB signal | 1072 | /* Receiving analog RGB signal |
1071 | * Set RGB full range (0-255) */ | 1073 | * Set RGB full range (0-255) */ |
1072 | io_write_and_or(sd, 0x02, 0x0f, 0x10); | 1074 | io_write_and_or(sd, 0x02, 0x0f, 0x10); |
1073 | break; | 1075 | break; |
1074 | } | 1076 | } |
1075 | 1077 | ||
1076 | if (state->selected_input == ADV7604_INPUT_VGA_COMP) { | 1078 | if (state->selected_input == ADV7604_PAD_VGA_COMP) { |
1077 | /* Receiving analog YPbPr signal | 1079 | /* Receiving analog YPbPr signal |
1078 | * Set automode */ | 1080 | * Set automode */ |
1079 | io_write_and_or(sd, 0x02, 0x0f, 0xf0); | 1081 | io_write_and_or(sd, 0x02, 0x0f, 0xf0); |
@@ -1106,7 +1108,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd) | |||
1106 | } | 1108 | } |
1107 | break; | 1109 | break; |
1108 | case V4L2_DV_RGB_RANGE_LIMITED: | 1110 | case V4L2_DV_RGB_RANGE_LIMITED: |
1109 | if (state->selected_input == ADV7604_INPUT_VGA_COMP) { | 1111 | if (state->selected_input == ADV7604_PAD_VGA_COMP) { |
1110 | /* YCrCb limited range (16-235) */ | 1112 | /* YCrCb limited range (16-235) */ |
1111 | io_write_and_or(sd, 0x02, 0x0f, 0x20); | 1113 | io_write_and_or(sd, 0x02, 0x0f, 0x20); |
1112 | break; | 1114 | break; |
@@ -1117,7 +1119,7 @@ static void set_rgb_quantization_range(struct v4l2_subdev *sd) | |||
1117 | 1119 | ||
1118 | break; | 1120 | break; |
1119 | case V4L2_DV_RGB_RANGE_FULL: | 1121 | case V4L2_DV_RGB_RANGE_FULL: |
1120 | if (state->selected_input == ADV7604_INPUT_VGA_COMP) { | 1122 | if (state->selected_input == ADV7604_PAD_VGA_COMP) { |
1121 | /* YCrCb full range (0-255) */ | 1123 | /* YCrCb full range (0-255) */ |
1122 | io_write_and_or(sd, 0x02, 0x0f, 0x60); | 1124 | io_write_and_or(sd, 0x02, 0x0f, 0x60); |
1123 | break; | 1125 | break; |
@@ -1806,7 +1808,7 @@ static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) | |||
1806 | struct adv7604_state *state = to_state(sd); | 1808 | struct adv7604_state *state = to_state(sd); |
1807 | u8 *data = NULL; | 1809 | u8 *data = NULL; |
1808 | 1810 | ||
1809 | if (edid->pad > ADV7604_EDID_PORT_D) | 1811 | if (edid->pad > ADV7604_PAD_HDMI_PORT_D) |
1810 | return -EINVAL; | 1812 | return -EINVAL; |
1811 | if (edid->blocks == 0) | 1813 | if (edid->blocks == 0) |
1812 | return -EINVAL; | 1814 | return -EINVAL; |
@@ -1821,10 +1823,10 @@ static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) | |||
1821 | edid->blocks = state->edid.blocks; | 1823 | edid->blocks = state->edid.blocks; |
1822 | 1824 | ||
1823 | switch (edid->pad) { | 1825 | switch (edid->pad) { |
1824 | case ADV7604_EDID_PORT_A: | 1826 | case ADV7604_PAD_HDMI_PORT_A: |
1825 | case ADV7604_EDID_PORT_B: | 1827 | case ADV7604_PAD_HDMI_PORT_B: |
1826 | case ADV7604_EDID_PORT_C: | 1828 | case ADV7604_PAD_HDMI_PORT_C: |
1827 | case ADV7604_EDID_PORT_D: | 1829 | case ADV7604_PAD_HDMI_PORT_D: |
1828 | if (state->edid.present & (1 << edid->pad)) | 1830 | if (state->edid.present & (1 << edid->pad)) |
1829 | data = state->edid.edid; | 1831 | data = state->edid.edid; |
1830 | break; | 1832 | break; |
@@ -1878,7 +1880,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) | |||
1878 | int err; | 1880 | int err; |
1879 | int i; | 1881 | int i; |
1880 | 1882 | ||
1881 | if (edid->pad > ADV7604_EDID_PORT_D) | 1883 | if (edid->pad > ADV7604_PAD_HDMI_PORT_D) |
1882 | return -EINVAL; | 1884 | return -EINVAL; |
1883 | if (edid->start_block != 0) | 1885 | if (edid->start_block != 0) |
1884 | return -EINVAL; | 1886 | return -EINVAL; |
@@ -1917,19 +1919,19 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) | |||
1917 | spa_loc = 0xc0; /* Default value [REF_02, p. 116] */ | 1919 | spa_loc = 0xc0; /* Default value [REF_02, p. 116] */ |
1918 | 1920 | ||
1919 | switch (edid->pad) { | 1921 | switch (edid->pad) { |
1920 | case ADV7604_EDID_PORT_A: | 1922 | case ADV7604_PAD_HDMI_PORT_A: |
1921 | state->spa_port_a[0] = edid->edid[spa_loc]; | 1923 | state->spa_port_a[0] = edid->edid[spa_loc]; |
1922 | state->spa_port_a[1] = edid->edid[spa_loc + 1]; | 1924 | state->spa_port_a[1] = edid->edid[spa_loc + 1]; |
1923 | break; | 1925 | break; |
1924 | case ADV7604_EDID_PORT_B: | 1926 | case ADV7604_PAD_HDMI_PORT_B: |
1925 | rep_write(sd, 0x70, edid->edid[spa_loc]); | 1927 | rep_write(sd, 0x70, edid->edid[spa_loc]); |
1926 | rep_write(sd, 0x71, edid->edid[spa_loc + 1]); | 1928 | rep_write(sd, 0x71, edid->edid[spa_loc + 1]); |
1927 | break; | 1929 | break; |
1928 | case ADV7604_EDID_PORT_C: | 1930 | case ADV7604_PAD_HDMI_PORT_C: |
1929 | rep_write(sd, 0x72, edid->edid[spa_loc]); | 1931 | rep_write(sd, 0x72, edid->edid[spa_loc]); |
1930 | rep_write(sd, 0x73, edid->edid[spa_loc + 1]); | 1932 | rep_write(sd, 0x73, edid->edid[spa_loc + 1]); |
1931 | break; | 1933 | break; |
1932 | case ADV7604_EDID_PORT_D: | 1934 | case ADV7604_PAD_HDMI_PORT_D: |
1933 | rep_write(sd, 0x74, edid->edid[spa_loc]); | 1935 | rep_write(sd, 0x74, edid->edid[spa_loc]); |
1934 | rep_write(sd, 0x75, edid->edid[spa_loc + 1]); | 1936 | rep_write(sd, 0x75, edid->edid[spa_loc + 1]); |
1935 | break; | 1937 | break; |
@@ -2429,7 +2431,7 @@ static const struct adv7604_chip_info adv7604_chip_info[] = { | |||
2429 | [ADV7604] = { | 2431 | [ADV7604] = { |
2430 | .type = ADV7604, | 2432 | .type = ADV7604, |
2431 | .has_afe = true, | 2433 | .has_afe = true, |
2432 | .max_port = ADV7604_INPUT_VGA_COMP, | 2434 | .max_port = ADV7604_PAD_VGA_COMP, |
2433 | .num_dv_ports = 4, | 2435 | .num_dv_ports = 4, |
2434 | .edid_enable_reg = 0x77, | 2436 | .edid_enable_reg = 0x77, |
2435 | .edid_status_reg = 0x7d, | 2437 | .edid_status_reg = 0x7d, |
@@ -2460,7 +2462,7 @@ static const struct adv7604_chip_info adv7604_chip_info[] = { | |||
2460 | [ADV7611] = { | 2462 | [ADV7611] = { |
2461 | .type = ADV7611, | 2463 | .type = ADV7611, |
2462 | .has_afe = false, | 2464 | .has_afe = false, |
2463 | .max_port = ADV7604_INPUT_HDMI_PORT_A, | 2465 | .max_port = ADV7604_PAD_HDMI_PORT_A, |
2464 | .num_dv_ports = 1, | 2466 | .num_dv_ports = 1, |
2465 | .edid_enable_reg = 0x74, | 2467 | .edid_enable_reg = 0x74, |
2466 | .edid_status_reg = 0x76, | 2468 | .edid_status_reg = 0x76, |
@@ -2494,6 +2496,7 @@ static int adv7604_probe(struct i2c_client *client, | |||
2494 | struct adv7604_platform_data *pdata = client->dev.platform_data; | 2496 | struct adv7604_platform_data *pdata = client->dev.platform_data; |
2495 | struct v4l2_ctrl_handler *hdl; | 2497 | struct v4l2_ctrl_handler *hdl; |
2496 | struct v4l2_subdev *sd; | 2498 | struct v4l2_subdev *sd; |
2499 | unsigned int i; | ||
2497 | u16 val; | 2500 | u16 val; |
2498 | int err; | 2501 | int err; |
2499 | 2502 | ||
@@ -2639,8 +2642,14 @@ static int adv7604_probe(struct i2c_client *client, | |||
2639 | INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug, | 2642 | INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug, |
2640 | adv7604_delayed_work_enable_hotplug); | 2643 | adv7604_delayed_work_enable_hotplug); |
2641 | 2644 | ||
2642 | state->pad.flags = MEDIA_PAD_FL_SOURCE; | 2645 | state->source_pad = state->info->num_dv_ports |
2643 | err = media_entity_init(&sd->entity, 1, &state->pad, 0); | 2646 | + (state->info->has_afe ? 2 : 0); |
2647 | for (i = 0; i < state->source_pad; ++i) | ||
2648 | state->pads[i].flags = MEDIA_PAD_FL_SINK; | ||
2649 | state->pads[state->source_pad].flags = MEDIA_PAD_FL_SOURCE; | ||
2650 | |||
2651 | err = media_entity_init(&sd->entity, state->source_pad + 1, | ||
2652 | state->pads, 0); | ||
2644 | if (err) | 2653 | if (err) |
2645 | goto err_work_queues; | 2654 | goto err_work_queues; |
2646 | 2655 | ||