diff options
-rw-r--r-- | drivers/media/i2c/adv7604.c | 719 | ||||
-rw-r--r-- | include/media/adv7604.h | 10 |
2 files changed, 528 insertions, 201 deletions
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c index f9503d2d1ed0..1720daf0c875 100644 --- a/drivers/media/i2c/adv7604.c +++ b/drivers/media/i2c/adv7604.c | |||
@@ -53,6 +53,43 @@ MODULE_LICENSE("GPL"); | |||
53 | /* ADV7604 system clock frequency */ | 53 | /* ADV7604 system clock frequency */ |
54 | #define ADV7604_fsc (28636360) | 54 | #define ADV7604_fsc (28636360) |
55 | 55 | ||
56 | enum adv7604_type { | ||
57 | ADV7604, | ||
58 | ADV7611, | ||
59 | }; | ||
60 | |||
61 | struct adv7604_reg_seq { | ||
62 | unsigned int reg; | ||
63 | u8 val; | ||
64 | }; | ||
65 | |||
66 | struct adv7604_chip_info { | ||
67 | enum adv7604_type type; | ||
68 | |||
69 | bool has_afe; | ||
70 | unsigned int max_port; | ||
71 | unsigned int num_dv_ports; | ||
72 | |||
73 | unsigned int edid_enable_reg; | ||
74 | unsigned int edid_status_reg; | ||
75 | unsigned int lcf_reg; | ||
76 | |||
77 | unsigned int cable_det_mask; | ||
78 | unsigned int tdms_lock_mask; | ||
79 | unsigned int fmt_change_digital_mask; | ||
80 | |||
81 | void (*set_termination)(struct v4l2_subdev *sd, bool enable); | ||
82 | void (*setup_irqs)(struct v4l2_subdev *sd); | ||
83 | unsigned int (*read_hdmi_pixelclock)(struct v4l2_subdev *sd); | ||
84 | unsigned int (*read_cable_det)(struct v4l2_subdev *sd); | ||
85 | |||
86 | /* 0 = AFE, 1 = HDMI */ | ||
87 | const struct adv7604_reg_seq *recommended_settings[2]; | ||
88 | unsigned int num_recommended_settings[2]; | ||
89 | |||
90 | unsigned long page_mask; | ||
91 | }; | ||
92 | |||
56 | /* | 93 | /* |
57 | ********************************************************************** | 94 | ********************************************************************** |
58 | * | 95 | * |
@@ -61,6 +98,7 @@ MODULE_LICENSE("GPL"); | |||
61 | ********************************************************************** | 98 | ********************************************************************** |
62 | */ | 99 | */ |
63 | struct adv7604_state { | 100 | struct adv7604_state { |
101 | const struct adv7604_chip_info *info; | ||
64 | struct adv7604_platform_data pdata; | 102 | struct adv7604_platform_data pdata; |
65 | struct v4l2_subdev sd; | 103 | struct v4l2_subdev sd; |
66 | struct media_pad pad; | 104 | struct media_pad pad; |
@@ -101,6 +139,11 @@ struct adv7604_state { | |||
101 | struct v4l2_ctrl *rgb_quantization_range_ctrl; | 139 | struct v4l2_ctrl *rgb_quantization_range_ctrl; |
102 | }; | 140 | }; |
103 | 141 | ||
142 | static bool adv7604_has_afe(struct adv7604_state *state) | ||
143 | { | ||
144 | return state->info->has_afe; | ||
145 | } | ||
146 | |||
104 | /* Supported CEA and DMT timings */ | 147 | /* Supported CEA and DMT timings */ |
105 | static const struct v4l2_dv_timings adv7604_timings[] = { | 148 | static const struct v4l2_dv_timings adv7604_timings[] = { |
106 | V4L2_DV_BT_CEA_720X480P59_94, | 149 | V4L2_DV_BT_CEA_720X480P59_94, |
@@ -611,6 +654,121 @@ static inline int vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val) | |||
611 | return adv_smbus_write_byte_data(state->i2c_vdp, reg, val); | 654 | return adv_smbus_write_byte_data(state->i2c_vdp, reg, val); |
612 | } | 655 | } |
613 | 656 | ||
657 | enum { | ||
658 | ADV7604_PAGE_IO, | ||
659 | ADV7604_PAGE_AVLINK, | ||
660 | ADV7604_PAGE_CEC, | ||
661 | ADV7604_PAGE_INFOFRAME, | ||
662 | ADV7604_PAGE_ESDP, | ||
663 | ADV7604_PAGE_DPP, | ||
664 | ADV7604_PAGE_AFE, | ||
665 | ADV7604_PAGE_REP, | ||
666 | ADV7604_PAGE_EDID, | ||
667 | ADV7604_PAGE_HDMI, | ||
668 | ADV7604_PAGE_TEST, | ||
669 | ADV7604_PAGE_CP, | ||
670 | ADV7604_PAGE_VDP, | ||
671 | ADV7604_PAGE_TERM, | ||
672 | }; | ||
673 | |||
674 | #define ADV7604_REG(page, offset) (((page) << 8) | (offset)) | ||
675 | #define ADV7604_REG_SEQ_TERM 0xffff | ||
676 | |||
677 | #ifdef CONFIG_VIDEO_ADV_DEBUG | ||
678 | static int adv7604_read_reg(struct v4l2_subdev *sd, unsigned int reg) | ||
679 | { | ||
680 | struct adv7604_state *state = to_state(sd); | ||
681 | unsigned int page = reg >> 8; | ||
682 | |||
683 | if (!(BIT(page) & state->info->page_mask)) | ||
684 | return -EINVAL; | ||
685 | |||
686 | reg &= 0xff; | ||
687 | |||
688 | switch (page) { | ||
689 | case ADV7604_PAGE_IO: | ||
690 | return io_read(sd, reg); | ||
691 | case ADV7604_PAGE_AVLINK: | ||
692 | return avlink_read(sd, reg); | ||
693 | case ADV7604_PAGE_CEC: | ||
694 | return cec_read(sd, reg); | ||
695 | case ADV7604_PAGE_INFOFRAME: | ||
696 | return infoframe_read(sd, reg); | ||
697 | case ADV7604_PAGE_ESDP: | ||
698 | return esdp_read(sd, reg); | ||
699 | case ADV7604_PAGE_DPP: | ||
700 | return dpp_read(sd, reg); | ||
701 | case ADV7604_PAGE_AFE: | ||
702 | return afe_read(sd, reg); | ||
703 | case ADV7604_PAGE_REP: | ||
704 | return rep_read(sd, reg); | ||
705 | case ADV7604_PAGE_EDID: | ||
706 | return edid_read(sd, reg); | ||
707 | case ADV7604_PAGE_HDMI: | ||
708 | return hdmi_read(sd, reg); | ||
709 | case ADV7604_PAGE_TEST: | ||
710 | return test_read(sd, reg); | ||
711 | case ADV7604_PAGE_CP: | ||
712 | return cp_read(sd, reg); | ||
713 | case ADV7604_PAGE_VDP: | ||
714 | return vdp_read(sd, reg); | ||
715 | } | ||
716 | |||
717 | return -EINVAL; | ||
718 | } | ||
719 | #endif | ||
720 | |||
721 | static int adv7604_write_reg(struct v4l2_subdev *sd, unsigned int reg, u8 val) | ||
722 | { | ||
723 | struct adv7604_state *state = to_state(sd); | ||
724 | unsigned int page = reg >> 8; | ||
725 | |||
726 | if (!(BIT(page) & state->info->page_mask)) | ||
727 | return -EINVAL; | ||
728 | |||
729 | reg &= 0xff; | ||
730 | |||
731 | switch (page) { | ||
732 | case ADV7604_PAGE_IO: | ||
733 | return io_write(sd, reg, val); | ||
734 | case ADV7604_PAGE_AVLINK: | ||
735 | return avlink_write(sd, reg, val); | ||
736 | case ADV7604_PAGE_CEC: | ||
737 | return cec_write(sd, reg, val); | ||
738 | case ADV7604_PAGE_INFOFRAME: | ||
739 | return infoframe_write(sd, reg, val); | ||
740 | case ADV7604_PAGE_ESDP: | ||
741 | return esdp_write(sd, reg, val); | ||
742 | case ADV7604_PAGE_DPP: | ||
743 | return dpp_write(sd, reg, val); | ||
744 | case ADV7604_PAGE_AFE: | ||
745 | return afe_write(sd, reg, val); | ||
746 | case ADV7604_PAGE_REP: | ||
747 | return rep_write(sd, reg, val); | ||
748 | case ADV7604_PAGE_EDID: | ||
749 | return edid_write(sd, reg, val); | ||
750 | case ADV7604_PAGE_HDMI: | ||
751 | return hdmi_write(sd, reg, val); | ||
752 | case ADV7604_PAGE_TEST: | ||
753 | return test_write(sd, reg, val); | ||
754 | case ADV7604_PAGE_CP: | ||
755 | return cp_write(sd, reg, val); | ||
756 | case ADV7604_PAGE_VDP: | ||
757 | return vdp_write(sd, reg, val); | ||
758 | } | ||
759 | |||
760 | return -EINVAL; | ||
761 | } | ||
762 | |||
763 | static void adv7604_write_reg_seq(struct v4l2_subdev *sd, | ||
764 | const struct adv7604_reg_seq *reg_seq) | ||
765 | { | ||
766 | unsigned int i; | ||
767 | |||
768 | for (i = 0; reg_seq[i].reg != ADV7604_REG_SEQ_TERM; i++) | ||
769 | adv7604_write_reg(sd, reg_seq[i].reg, reg_seq[i].val); | ||
770 | } | ||
771 | |||
614 | /* ----------------------------------------------------------------------- */ | 772 | /* ----------------------------------------------------------------------- */ |
615 | 773 | ||
616 | static inline bool is_analog_input(struct v4l2_subdev *sd) | 774 | static inline bool is_analog_input(struct v4l2_subdev *sd) |
@@ -654,119 +812,61 @@ static void adv7604_inv_register(struct v4l2_subdev *sd) | |||
654 | static int adv7604_g_register(struct v4l2_subdev *sd, | 812 | static int adv7604_g_register(struct v4l2_subdev *sd, |
655 | struct v4l2_dbg_register *reg) | 813 | struct v4l2_dbg_register *reg) |
656 | { | 814 | { |
657 | reg->size = 1; | 815 | int ret; |
658 | switch (reg->reg >> 8) { | 816 | |
659 | case 0: | 817 | ret = adv7604_read_reg(sd, reg->reg); |
660 | reg->val = io_read(sd, reg->reg & 0xff); | 818 | if (ret < 0) { |
661 | break; | ||
662 | case 1: | ||
663 | reg->val = avlink_read(sd, reg->reg & 0xff); | ||
664 | break; | ||
665 | case 2: | ||
666 | reg->val = cec_read(sd, reg->reg & 0xff); | ||
667 | break; | ||
668 | case 3: | ||
669 | reg->val = infoframe_read(sd, reg->reg & 0xff); | ||
670 | break; | ||
671 | case 4: | ||
672 | reg->val = esdp_read(sd, reg->reg & 0xff); | ||
673 | break; | ||
674 | case 5: | ||
675 | reg->val = dpp_read(sd, reg->reg & 0xff); | ||
676 | break; | ||
677 | case 6: | ||
678 | reg->val = afe_read(sd, reg->reg & 0xff); | ||
679 | break; | ||
680 | case 7: | ||
681 | reg->val = rep_read(sd, reg->reg & 0xff); | ||
682 | break; | ||
683 | case 8: | ||
684 | reg->val = edid_read(sd, reg->reg & 0xff); | ||
685 | break; | ||
686 | case 9: | ||
687 | reg->val = hdmi_read(sd, reg->reg & 0xff); | ||
688 | break; | ||
689 | case 0xa: | ||
690 | reg->val = test_read(sd, reg->reg & 0xff); | ||
691 | break; | ||
692 | case 0xb: | ||
693 | reg->val = cp_read(sd, reg->reg & 0xff); | ||
694 | break; | ||
695 | case 0xc: | ||
696 | reg->val = vdp_read(sd, reg->reg & 0xff); | ||
697 | break; | ||
698 | default: | ||
699 | v4l2_info(sd, "Register %03llx not supported\n", reg->reg); | 819 | v4l2_info(sd, "Register %03llx not supported\n", reg->reg); |
700 | adv7604_inv_register(sd); | 820 | adv7604_inv_register(sd); |
701 | break; | 821 | return ret; |
702 | } | 822 | } |
823 | |||
824 | reg->size = 1; | ||
825 | reg->val = ret; | ||
826 | |||
703 | return 0; | 827 | return 0; |
704 | } | 828 | } |
705 | 829 | ||
706 | static int adv7604_s_register(struct v4l2_subdev *sd, | 830 | static int adv7604_s_register(struct v4l2_subdev *sd, |
707 | const struct v4l2_dbg_register *reg) | 831 | const struct v4l2_dbg_register *reg) |
708 | { | 832 | { |
709 | u8 val = reg->val & 0xff; | 833 | int ret; |
710 | 834 | ||
711 | switch (reg->reg >> 8) { | 835 | ret = adv7604_write_reg(sd, reg->reg, reg->val); |
712 | case 0: | 836 | if (ret < 0) { |
713 | io_write(sd, reg->reg & 0xff, val); | ||
714 | break; | ||
715 | case 1: | ||
716 | avlink_write(sd, reg->reg & 0xff, val); | ||
717 | break; | ||
718 | case 2: | ||
719 | cec_write(sd, reg->reg & 0xff, val); | ||
720 | break; | ||
721 | case 3: | ||
722 | infoframe_write(sd, reg->reg & 0xff, val); | ||
723 | break; | ||
724 | case 4: | ||
725 | esdp_write(sd, reg->reg & 0xff, val); | ||
726 | break; | ||
727 | case 5: | ||
728 | dpp_write(sd, reg->reg & 0xff, val); | ||
729 | break; | ||
730 | case 6: | ||
731 | afe_write(sd, reg->reg & 0xff, val); | ||
732 | break; | ||
733 | case 7: | ||
734 | rep_write(sd, reg->reg & 0xff, val); | ||
735 | break; | ||
736 | case 8: | ||
737 | edid_write(sd, reg->reg & 0xff, val); | ||
738 | break; | ||
739 | case 9: | ||
740 | hdmi_write(sd, reg->reg & 0xff, val); | ||
741 | break; | ||
742 | case 0xa: | ||
743 | test_write(sd, reg->reg & 0xff, val); | ||
744 | break; | ||
745 | case 0xb: | ||
746 | cp_write(sd, reg->reg & 0xff, val); | ||
747 | break; | ||
748 | case 0xc: | ||
749 | vdp_write(sd, reg->reg & 0xff, val); | ||
750 | break; | ||
751 | default: | ||
752 | v4l2_info(sd, "Register %03llx not supported\n", reg->reg); | 837 | v4l2_info(sd, "Register %03llx not supported\n", reg->reg); |
753 | adv7604_inv_register(sd); | 838 | adv7604_inv_register(sd); |
754 | break; | 839 | return ret; |
755 | } | 840 | } |
841 | |||
756 | return 0; | 842 | return 0; |
757 | } | 843 | } |
758 | #endif | 844 | #endif |
759 | 845 | ||
846 | static unsigned int adv7604_read_cable_det(struct v4l2_subdev *sd) | ||
847 | { | ||
848 | u8 value = io_read(sd, 0x6f); | ||
849 | |||
850 | return ((value & 0x10) >> 4) | ||
851 | | ((value & 0x08) >> 2) | ||
852 | | ((value & 0x04) << 0) | ||
853 | | ((value & 0x02) << 2); | ||
854 | } | ||
855 | |||
856 | static unsigned int adv7611_read_cable_det(struct v4l2_subdev *sd) | ||
857 | { | ||
858 | u8 value = io_read(sd, 0x6f); | ||
859 | |||
860 | return value & 1; | ||
861 | } | ||
862 | |||
760 | static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd) | 863 | static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd) |
761 | { | 864 | { |
762 | struct adv7604_state *state = to_state(sd); | 865 | struct adv7604_state *state = to_state(sd); |
763 | u8 reg_io_6f = io_read(sd, 0x6f); | 866 | const struct adv7604_chip_info *info = state->info; |
764 | 867 | ||
765 | return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, | 868 | return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl, |
766 | ((reg_io_6f & 0x10) >> 4) | | 869 | info->read_cable_det(sd)); |
767 | ((reg_io_6f & 0x08) >> 2) | | ||
768 | (reg_io_6f & 0x04) | | ||
769 | ((reg_io_6f & 0x02) << 2)); | ||
770 | } | 870 | } |
771 | 871 | ||
772 | static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd, | 872 | static int find_and_set_predefined_video_timings(struct v4l2_subdev *sd, |
@@ -797,9 +897,11 @@ static int configure_predefined_video_timings(struct v4l2_subdev *sd, | |||
797 | 897 | ||
798 | v4l2_dbg(1, debug, sd, "%s", __func__); | 898 | v4l2_dbg(1, debug, sd, "%s", __func__); |
799 | 899 | ||
800 | /* reset to default values */ | 900 | if (adv7604_has_afe(state)) { |
801 | io_write(sd, 0x16, 0x43); | 901 | /* reset to default values */ |
802 | io_write(sd, 0x17, 0x5a); | 902 | io_write(sd, 0x16, 0x43); |
903 | io_write(sd, 0x17, 0x5a); | ||
904 | } | ||
803 | /* disable embedded syncs for auto graphics mode */ | 905 | /* disable embedded syncs for auto graphics mode */ |
804 | cp_write_and_or(sd, 0x81, 0xef, 0x00); | 906 | cp_write_and_or(sd, 0x81, 0xef, 0x00); |
805 | cp_write(sd, 0x8f, 0x00); | 907 | cp_write(sd, 0x8f, 0x00); |
@@ -1061,6 +1163,8 @@ static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl) | |||
1061 | set_rgb_quantization_range(sd); | 1163 | set_rgb_quantization_range(sd); |
1062 | return 0; | 1164 | return 0; |
1063 | case V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE: | 1165 | case V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE: |
1166 | if (!adv7604_has_afe(state)) | ||
1167 | return -EINVAL; | ||
1064 | /* Set the analog sampling phase. This is needed to find the | 1168 | /* Set the analog sampling phase. This is needed to find the |
1065 | best sampling phase for analog video: an application or | 1169 | best sampling phase for analog video: an application or |
1066 | driver has to try a number of phases and analyze the picture | 1170 | driver has to try a number of phases and analyze the picture |
@@ -1098,7 +1202,10 @@ static inline bool no_signal_tmds(struct v4l2_subdev *sd) | |||
1098 | 1202 | ||
1099 | static inline bool no_lock_tmds(struct v4l2_subdev *sd) | 1203 | static inline bool no_lock_tmds(struct v4l2_subdev *sd) |
1100 | { | 1204 | { |
1101 | return (io_read(sd, 0x6a) & 0xe0) != 0xe0; | 1205 | struct adv7604_state *state = to_state(sd); |
1206 | const struct adv7604_chip_info *info = state->info; | ||
1207 | |||
1208 | return (io_read(sd, 0x6a) & info->tdms_lock_mask) != info->tdms_lock_mask; | ||
1102 | } | 1209 | } |
1103 | 1210 | ||
1104 | static inline bool is_hdmi(struct v4l2_subdev *sd) | 1211 | static inline bool is_hdmi(struct v4l2_subdev *sd) |
@@ -1108,6 +1215,15 @@ static inline bool is_hdmi(struct v4l2_subdev *sd) | |||
1108 | 1215 | ||
1109 | static inline bool no_lock_sspd(struct v4l2_subdev *sd) | 1216 | static inline bool no_lock_sspd(struct v4l2_subdev *sd) |
1110 | { | 1217 | { |
1218 | struct adv7604_state *state = to_state(sd); | ||
1219 | |||
1220 | /* | ||
1221 | * Chips without a AFE don't expose registers for the SSPD, so just assume | ||
1222 | * that we have a lock. | ||
1223 | */ | ||
1224 | if (adv7604_has_afe(state)) | ||
1225 | return false; | ||
1226 | |||
1111 | /* TODO channel 2 */ | 1227 | /* TODO channel 2 */ |
1112 | return ((cp_read(sd, 0xb5) & 0xd0) != 0xd0); | 1228 | return ((cp_read(sd, 0xb5) & 0xd0) != 0xd0); |
1113 | } | 1229 | } |
@@ -1137,6 +1253,11 @@ static inline bool no_signal(struct v4l2_subdev *sd) | |||
1137 | 1253 | ||
1138 | static inline bool no_lock_cp(struct v4l2_subdev *sd) | 1254 | static inline bool no_lock_cp(struct v4l2_subdev *sd) |
1139 | { | 1255 | { |
1256 | struct adv7604_state *state = to_state(sd); | ||
1257 | |||
1258 | if (!adv7604_has_afe(state)) | ||
1259 | return false; | ||
1260 | |||
1140 | /* CP has detected a non standard number of lines on the incoming | 1261 | /* CP has detected a non standard number of lines on the incoming |
1141 | video compared to what it is configured to receive by s_dv_timings */ | 1262 | video compared to what it is configured to receive by s_dv_timings */ |
1142 | return io_read(sd, 0x12) & 0x01; | 1263 | return io_read(sd, 0x12) & 0x01; |
@@ -1205,8 +1326,11 @@ static int stdi2dv_timings(struct v4l2_subdev *sd, | |||
1205 | return -1; | 1326 | return -1; |
1206 | } | 1327 | } |
1207 | 1328 | ||
1329 | |||
1208 | static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi) | 1330 | static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi) |
1209 | { | 1331 | { |
1332 | struct adv7604_state *state = to_state(sd); | ||
1333 | const struct adv7604_chip_info *info = state->info; | ||
1210 | u8 polarity; | 1334 | u8 polarity; |
1211 | 1335 | ||
1212 | if (no_lock_stdi(sd) || no_lock_sspd(sd)) { | 1336 | if (no_lock_stdi(sd) || no_lock_sspd(sd)) { |
@@ -1216,20 +1340,26 @@ static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi) | |||
1216 | 1340 | ||
1217 | /* read STDI */ | 1341 | /* read STDI */ |
1218 | stdi->bl = cp_read16(sd, 0xb1, 0x3fff); | 1342 | stdi->bl = cp_read16(sd, 0xb1, 0x3fff); |
1219 | stdi->lcf = cp_read16(sd, 0xb3, 0x7ff); | 1343 | stdi->lcf = cp_read16(sd, info->lcf_reg, 0x7ff); |
1220 | stdi->lcvs = cp_read(sd, 0xb3) >> 3; | 1344 | stdi->lcvs = cp_read(sd, 0xb3) >> 3; |
1221 | stdi->interlaced = io_read(sd, 0x12) & 0x10; | 1345 | stdi->interlaced = io_read(sd, 0x12) & 0x10; |
1222 | 1346 | ||
1223 | /* read SSPD */ | 1347 | if (adv7604_has_afe(state)) { |
1224 | polarity = cp_read(sd, 0xb5); | 1348 | /* read SSPD */ |
1225 | if ((polarity & 0x03) == 0x01) { | 1349 | polarity = cp_read(sd, 0xb5); |
1226 | stdi->hs_pol = polarity & 0x10 | 1350 | if ((polarity & 0x03) == 0x01) { |
1227 | ? (polarity & 0x08 ? '+' : '-') : 'x'; | 1351 | stdi->hs_pol = polarity & 0x10 |
1228 | stdi->vs_pol = polarity & 0x40 | 1352 | ? (polarity & 0x08 ? '+' : '-') : 'x'; |
1229 | ? (polarity & 0x20 ? '+' : '-') : 'x'; | 1353 | stdi->vs_pol = polarity & 0x40 |
1354 | ? (polarity & 0x20 ? '+' : '-') : 'x'; | ||
1355 | } else { | ||
1356 | stdi->hs_pol = 'x'; | ||
1357 | stdi->vs_pol = 'x'; | ||
1358 | } | ||
1230 | } else { | 1359 | } else { |
1231 | stdi->hs_pol = 'x'; | 1360 | polarity = hdmi_read(sd, 0x05); |
1232 | stdi->vs_pol = 'x'; | 1361 | stdi->hs_pol = polarity & 0x20 ? '+' : '-'; |
1362 | stdi->vs_pol = polarity & 0x10 ? '+' : '-'; | ||
1233 | } | 1363 | } |
1234 | 1364 | ||
1235 | if (no_lock_stdi(sd) || no_lock_sspd(sd)) { | 1365 | if (no_lock_stdi(sd) || no_lock_sspd(sd)) { |
@@ -1297,10 +1427,43 @@ static void adv7604_fill_optional_dv_timings_fields(struct v4l2_subdev *sd, | |||
1297 | } | 1427 | } |
1298 | } | 1428 | } |
1299 | 1429 | ||
1430 | static unsigned int adv7604_read_hdmi_pixelclock(struct v4l2_subdev *sd) | ||
1431 | { | ||
1432 | unsigned int freq; | ||
1433 | int a, b; | ||
1434 | |||
1435 | a = hdmi_read(sd, 0x06); | ||
1436 | b = hdmi_read(sd, 0x3b); | ||
1437 | if (a < 0 || b < 0) | ||
1438 | return 0; | ||
1439 | freq = a * 1000000 + ((b & 0x30) >> 4) * 250000; | ||
1440 | |||
1441 | if (is_hdmi(sd)) { | ||
1442 | /* adjust for deep color mode */ | ||
1443 | unsigned bits_per_channel = ((hdmi_read(sd, 0x0b) & 0x60) >> 4) + 8; | ||
1444 | |||
1445 | freq = freq * 8 / bits_per_channel; | ||
1446 | } | ||
1447 | |||
1448 | return freq; | ||
1449 | } | ||
1450 | |||
1451 | static unsigned int adv7611_read_hdmi_pixelclock(struct v4l2_subdev *sd) | ||
1452 | { | ||
1453 | int a, b; | ||
1454 | |||
1455 | a = hdmi_read(sd, 0x51); | ||
1456 | b = hdmi_read(sd, 0x52); | ||
1457 | if (a < 0 || b < 0) | ||
1458 | return 0; | ||
1459 | return ((a << 1) | (b >> 7)) * 1000000 + (b & 0x7f) * 1000000 / 128; | ||
1460 | } | ||
1461 | |||
1300 | static int adv7604_query_dv_timings(struct v4l2_subdev *sd, | 1462 | static int adv7604_query_dv_timings(struct v4l2_subdev *sd, |
1301 | struct v4l2_dv_timings *timings) | 1463 | struct v4l2_dv_timings *timings) |
1302 | { | 1464 | { |
1303 | struct adv7604_state *state = to_state(sd); | 1465 | struct adv7604_state *state = to_state(sd); |
1466 | const struct adv7604_chip_info *info = state->info; | ||
1304 | struct v4l2_bt_timings *bt = &timings->bt; | 1467 | struct v4l2_bt_timings *bt = &timings->bt; |
1305 | struct stdi_readback stdi; | 1468 | struct stdi_readback stdi; |
1306 | 1469 | ||
@@ -1324,21 +1487,12 @@ static int adv7604_query_dv_timings(struct v4l2_subdev *sd, | |||
1324 | V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE; | 1487 | V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE; |
1325 | 1488 | ||
1326 | if (is_digital_input(sd)) { | 1489 | if (is_digital_input(sd)) { |
1327 | uint32_t freq; | ||
1328 | |||
1329 | timings->type = V4L2_DV_BT_656_1120; | 1490 | timings->type = V4L2_DV_BT_656_1120; |
1330 | 1491 | ||
1492 | /* FIXME: All masks are incorrect for ADV7611 */ | ||
1331 | bt->width = hdmi_read16(sd, 0x07, 0xfff); | 1493 | bt->width = hdmi_read16(sd, 0x07, 0xfff); |
1332 | bt->height = hdmi_read16(sd, 0x09, 0xfff); | 1494 | bt->height = hdmi_read16(sd, 0x09, 0xfff); |
1333 | freq = (hdmi_read(sd, 0x06) * 1000000) + | 1495 | bt->pixelclock = info->read_hdmi_pixelclock(sd); |
1334 | ((hdmi_read(sd, 0x3b) & 0x30) >> 4) * 250000; | ||
1335 | if (is_hdmi(sd)) { | ||
1336 | /* adjust for deep color mode */ | ||
1337 | unsigned bits_per_channel = ((hdmi_read(sd, 0x0b) & 0x60) >> 4) + 8; | ||
1338 | |||
1339 | freq = freq * 8 / bits_per_channel; | ||
1340 | } | ||
1341 | bt->pixelclock = freq; | ||
1342 | bt->hfrontporch = hdmi_read16(sd, 0x20, 0x3ff); | 1496 | bt->hfrontporch = hdmi_read16(sd, 0x20, 0x3ff); |
1343 | bt->hsync = hdmi_read16(sd, 0x22, 0x3ff); | 1497 | bt->hsync = hdmi_read16(sd, 0x22, 0x3ff); |
1344 | bt->hbackporch = hdmi_read16(sd, 0x24, 0x3ff); | 1498 | bt->hbackporch = hdmi_read16(sd, 0x24, 0x3ff); |
@@ -1444,7 +1598,7 @@ static int adv7604_s_dv_timings(struct v4l2_subdev *sd, | |||
1444 | 1598 | ||
1445 | state->timings = *timings; | 1599 | state->timings = *timings; |
1446 | 1600 | ||
1447 | cp_write(sd, 0x91, bt->interlaced ? 0x50 : 0x10); | 1601 | cp_write_and_or(sd, 0x91, 0xbf, bt->interlaced ? 0x40 : 0x00); |
1448 | 1602 | ||
1449 | /* Use prim_mode and vid_std when available */ | 1603 | /* Use prim_mode and vid_std when available */ |
1450 | err = configure_predefined_video_timings(sd, timings); | 1604 | err = configure_predefined_video_timings(sd, timings); |
@@ -1471,6 +1625,16 @@ static int adv7604_g_dv_timings(struct v4l2_subdev *sd, | |||
1471 | return 0; | 1625 | return 0; |
1472 | } | 1626 | } |
1473 | 1627 | ||
1628 | static void adv7604_set_termination(struct v4l2_subdev *sd, bool enable) | ||
1629 | { | ||
1630 | hdmi_write(sd, 0x01, enable ? 0x00 : 0x78); | ||
1631 | } | ||
1632 | |||
1633 | static void adv7611_set_termination(struct v4l2_subdev *sd, bool enable) | ||
1634 | { | ||
1635 | hdmi_write(sd, 0x83, enable ? 0xfe : 0xff); | ||
1636 | } | ||
1637 | |||
1474 | static void enable_input(struct v4l2_subdev *sd) | 1638 | static void enable_input(struct v4l2_subdev *sd) |
1475 | { | 1639 | { |
1476 | struct adv7604_state *state = to_state(sd); | 1640 | struct adv7604_state *state = to_state(sd); |
@@ -1479,7 +1643,7 @@ static void enable_input(struct v4l2_subdev *sd) | |||
1479 | io_write(sd, 0x15, 0xb0); /* Disable Tristate of Pins (no audio) */ | 1643 | io_write(sd, 0x15, 0xb0); /* Disable Tristate of Pins (no audio) */ |
1480 | } else if (is_digital_input(sd)) { | 1644 | } else if (is_digital_input(sd)) { |
1481 | hdmi_write_and_or(sd, 0x00, 0xfc, state->selected_input); | 1645 | hdmi_write_and_or(sd, 0x00, 0xfc, state->selected_input); |
1482 | hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */ | 1646 | state->info->set_termination(sd, true); |
1483 | io_write(sd, 0x15, 0xa0); /* Disable Tristate of Pins */ | 1647 | io_write(sd, 0x15, 0xa0); /* Disable Tristate of Pins */ |
1484 | hdmi_write_and_or(sd, 0x1a, 0xef, 0x00); /* Unmute audio */ | 1648 | hdmi_write_and_or(sd, 0x1a, 0xef, 0x00); /* Unmute audio */ |
1485 | } else { | 1649 | } else { |
@@ -1490,67 +1654,36 @@ static void enable_input(struct v4l2_subdev *sd) | |||
1490 | 1654 | ||
1491 | static void disable_input(struct v4l2_subdev *sd) | 1655 | static void disable_input(struct v4l2_subdev *sd) |
1492 | { | 1656 | { |
1657 | struct adv7604_state *state = to_state(sd); | ||
1658 | |||
1493 | hdmi_write_and_or(sd, 0x1a, 0xef, 0x10); /* Mute audio */ | 1659 | hdmi_write_and_or(sd, 0x1a, 0xef, 0x10); /* Mute audio */ |
1494 | msleep(16); /* 512 samples with >= 32 kHz sample rate [REF_03, c. 7.16.10] */ | 1660 | msleep(16); /* 512 samples with >= 32 kHz sample rate [REF_03, c. 7.16.10] */ |
1495 | io_write(sd, 0x15, 0xbe); /* Tristate all outputs from video core */ | 1661 | io_write(sd, 0x15, 0xbe); /* Tristate all outputs from video core */ |
1496 | hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */ | 1662 | state->info->set_termination(sd, false); |
1497 | } | 1663 | } |
1498 | 1664 | ||
1499 | static void select_input(struct v4l2_subdev *sd) | 1665 | static void select_input(struct v4l2_subdev *sd) |
1500 | { | 1666 | { |
1501 | struct adv7604_state *state = to_state(sd); | 1667 | struct adv7604_state *state = to_state(sd); |
1668 | const struct adv7604_chip_info *info = state->info; | ||
1502 | 1669 | ||
1503 | if (is_analog_input(sd)) { | 1670 | if (is_analog_input(sd)) { |
1504 | /* reset ADI recommended settings for HDMI: */ | 1671 | adv7604_write_reg_seq(sd, info->recommended_settings[0]); |
1505 | /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */ | ||
1506 | hdmi_write(sd, 0x0d, 0x04); /* HDMI filter optimization */ | ||
1507 | hdmi_write(sd, 0x3d, 0x00); /* DDC bus active pull-up control */ | ||
1508 | hdmi_write(sd, 0x3e, 0x74); /* TMDS PLL optimization */ | ||
1509 | hdmi_write(sd, 0x4e, 0x3b); /* TMDS PLL optimization */ | ||
1510 | hdmi_write(sd, 0x57, 0x74); /* TMDS PLL optimization */ | ||
1511 | hdmi_write(sd, 0x58, 0x63); /* TMDS PLL optimization */ | ||
1512 | hdmi_write(sd, 0x8d, 0x18); /* equaliser */ | ||
1513 | hdmi_write(sd, 0x8e, 0x34); /* equaliser */ | ||
1514 | hdmi_write(sd, 0x93, 0x88); /* equaliser */ | ||
1515 | hdmi_write(sd, 0x94, 0x2e); /* equaliser */ | ||
1516 | hdmi_write(sd, 0x96, 0x00); /* enable automatic EQ changing */ | ||
1517 | 1672 | ||
1518 | afe_write(sd, 0x00, 0x08); /* power up ADC */ | 1673 | afe_write(sd, 0x00, 0x08); /* power up ADC */ |
1519 | afe_write(sd, 0x01, 0x06); /* power up Analog Front End */ | 1674 | afe_write(sd, 0x01, 0x06); /* power up Analog Front End */ |
1520 | afe_write(sd, 0xc8, 0x00); /* phase control */ | 1675 | afe_write(sd, 0xc8, 0x00); /* phase control */ |
1521 | |||
1522 | /* set ADI recommended settings for digitizer */ | ||
1523 | /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */ | ||
1524 | afe_write(sd, 0x12, 0x7b); /* ADC noise shaping filter controls */ | ||
1525 | afe_write(sd, 0x0c, 0x1f); /* CP core gain controls */ | ||
1526 | cp_write(sd, 0x3e, 0x04); /* CP core pre-gain control */ | ||
1527 | cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */ | ||
1528 | cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */ | ||
1529 | } else if (is_digital_input(sd)) { | 1676 | } else if (is_digital_input(sd)) { |
1530 | hdmi_write(sd, 0x00, state->selected_input & 0x03); | 1677 | hdmi_write(sd, 0x00, state->selected_input & 0x03); |
1531 | 1678 | ||
1532 | /* set ADI recommended settings for HDMI: */ | 1679 | adv7604_write_reg_seq(sd, info->recommended_settings[1]); |
1533 | /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */ | 1680 | |
1534 | hdmi_write(sd, 0x0d, 0x84); /* HDMI filter optimization */ | 1681 | if (adv7604_has_afe(state)) { |
1535 | hdmi_write(sd, 0x3d, 0x10); /* DDC bus active pull-up control */ | 1682 | afe_write(sd, 0x00, 0xff); /* power down ADC */ |
1536 | hdmi_write(sd, 0x3e, 0x39); /* TMDS PLL optimization */ | 1683 | afe_write(sd, 0x01, 0xfe); /* power down Analog Front End */ |
1537 | hdmi_write(sd, 0x4e, 0x3b); /* TMDS PLL optimization */ | 1684 | afe_write(sd, 0xc8, 0x40); /* phase control */ |
1538 | hdmi_write(sd, 0x57, 0xb6); /* TMDS PLL optimization */ | 1685 | } |
1539 | hdmi_write(sd, 0x58, 0x03); /* TMDS PLL optimization */ | 1686 | |
1540 | hdmi_write(sd, 0x8d, 0x18); /* equaliser */ | ||
1541 | hdmi_write(sd, 0x8e, 0x34); /* equaliser */ | ||
1542 | hdmi_write(sd, 0x93, 0x8b); /* equaliser */ | ||
1543 | hdmi_write(sd, 0x94, 0x2d); /* equaliser */ | ||
1544 | hdmi_write(sd, 0x96, 0x01); /* enable automatic EQ changing */ | ||
1545 | |||
1546 | afe_write(sd, 0x00, 0xff); /* power down ADC */ | ||
1547 | afe_write(sd, 0x01, 0xfe); /* power down Analog Front End */ | ||
1548 | afe_write(sd, 0xc8, 0x40); /* phase control */ | ||
1549 | |||
1550 | /* reset ADI recommended settings for digitizer */ | ||
1551 | /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */ | ||
1552 | afe_write(sd, 0x12, 0xfb); /* ADC noise shaping filter controls */ | ||
1553 | afe_write(sd, 0x0c, 0x0d); /* CP core gain controls */ | ||
1554 | cp_write(sd, 0x3e, 0x00); /* CP core pre-gain control */ | 1687 | cp_write(sd, 0x3e, 0x00); /* CP core pre-gain control */ |
1555 | cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */ | 1688 | cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */ |
1556 | cp_write(sd, 0x40, 0x80); /* CP core pre-gain control. Graphics mode */ | 1689 | cp_write(sd, 0x40, 0x80); /* CP core pre-gain control. Graphics mode */ |
@@ -1571,6 +1704,9 @@ static int adv7604_s_routing(struct v4l2_subdev *sd, | |||
1571 | if (input == state->selected_input) | 1704 | if (input == state->selected_input) |
1572 | return 0; | 1705 | return 0; |
1573 | 1706 | ||
1707 | if (input > state->info->max_port) | ||
1708 | return -EINVAL; | ||
1709 | |||
1574 | state->selected_input = input; | 1710 | state->selected_input = input; |
1575 | 1711 | ||
1576 | disable_input(sd); | 1712 | disable_input(sd); |
@@ -1610,6 +1746,8 @@ static int adv7604_g_mbus_fmt(struct v4l2_subdev *sd, | |||
1610 | 1746 | ||
1611 | static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled) | 1747 | static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled) |
1612 | { | 1748 | { |
1749 | struct adv7604_state *state = to_state(sd); | ||
1750 | const struct adv7604_chip_info *info = state->info; | ||
1613 | const u8 irq_reg_0x43 = io_read(sd, 0x43); | 1751 | const u8 irq_reg_0x43 = io_read(sd, 0x43); |
1614 | const u8 irq_reg_0x6b = io_read(sd, 0x6b); | 1752 | const u8 irq_reg_0x6b = io_read(sd, 0x6b); |
1615 | const u8 irq_reg_0x70 = io_read(sd, 0x70); | 1753 | const u8 irq_reg_0x70 = io_read(sd, 0x70); |
@@ -1628,7 +1766,9 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled) | |||
1628 | 1766 | ||
1629 | /* format change */ | 1767 | /* format change */ |
1630 | fmt_change = irq_reg_0x43 & 0x98; | 1768 | fmt_change = irq_reg_0x43 & 0x98; |
1631 | fmt_change_digital = is_digital_input(sd) ? (irq_reg_0x6b & 0xc0) : 0; | 1769 | fmt_change_digital = is_digital_input(sd) |
1770 | ? irq_reg_0x6b & info->fmt_change_digital_mask | ||
1771 | : 0; | ||
1632 | 1772 | ||
1633 | if (fmt_change || fmt_change_digital) { | 1773 | if (fmt_change || fmt_change_digital) { |
1634 | v4l2_dbg(1, debug, sd, | 1774 | v4l2_dbg(1, debug, sd, |
@@ -1650,7 +1790,7 @@ static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled) | |||
1650 | } | 1790 | } |
1651 | 1791 | ||
1652 | /* tx 5v detect */ | 1792 | /* tx 5v detect */ |
1653 | tx_5v = io_read(sd, 0x70) & 0x1e; | 1793 | tx_5v = io_read(sd, 0x70) & info->cable_det_mask; |
1654 | if (tx_5v) { | 1794 | if (tx_5v) { |
1655 | v4l2_dbg(1, debug, sd, "%s: tx_5v: 0x%x\n", __func__, tx_5v); | 1795 | v4l2_dbg(1, debug, sd, "%s: tx_5v: 0x%x\n", __func__, tx_5v); |
1656 | io_write(sd, 0x71, tx_5v); | 1796 | io_write(sd, 0x71, tx_5v); |
@@ -1732,6 +1872,7 @@ static int get_edid_spa_location(const u8 *edid) | |||
1732 | static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) | 1872 | static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) |
1733 | { | 1873 | { |
1734 | struct adv7604_state *state = to_state(sd); | 1874 | struct adv7604_state *state = to_state(sd); |
1875 | const struct adv7604_chip_info *info = state->info; | ||
1735 | int spa_loc; | 1876 | int spa_loc; |
1736 | int tmp = 0; | 1877 | int tmp = 0; |
1737 | int err; | 1878 | int err; |
@@ -1745,7 +1886,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) | |||
1745 | /* Disable hotplug and I2C access to EDID RAM from DDC port */ | 1886 | /* Disable hotplug and I2C access to EDID RAM from DDC port */ |
1746 | state->edid.present &= ~(1 << edid->pad); | 1887 | state->edid.present &= ~(1 << edid->pad); |
1747 | v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present); | 1888 | v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&state->edid.present); |
1748 | rep_write_and_or(sd, 0x77, 0xf0, state->edid.present); | 1889 | rep_write_and_or(sd, info->edid_enable_reg, 0xf0, state->edid.present); |
1749 | 1890 | ||
1750 | /* Fall back to a 16:9 aspect ratio */ | 1891 | /* Fall back to a 16:9 aspect ratio */ |
1751 | state->aspect_ratio.numerator = 16; | 1892 | state->aspect_ratio.numerator = 16; |
@@ -1769,7 +1910,7 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) | |||
1769 | /* Disable hotplug and I2C access to EDID RAM from DDC port */ | 1910 | /* Disable hotplug and I2C access to EDID RAM from DDC port */ |
1770 | cancel_delayed_work_sync(&state->delayed_work_enable_hotplug); | 1911 | cancel_delayed_work_sync(&state->delayed_work_enable_hotplug); |
1771 | v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&tmp); | 1912 | v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)&tmp); |
1772 | rep_write_and_or(sd, 0x77, 0xf0, 0x00); | 1913 | rep_write_and_or(sd, info->edid_enable_reg, 0xf0, 0x00); |
1773 | 1914 | ||
1774 | spa_loc = get_edid_spa_location(edid->edid); | 1915 | spa_loc = get_edid_spa_location(edid->edid); |
1775 | if (spa_loc < 0) | 1916 | if (spa_loc < 0) |
@@ -1795,8 +1936,14 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) | |||
1795 | default: | 1936 | default: |
1796 | return -EINVAL; | 1937 | return -EINVAL; |
1797 | } | 1938 | } |
1798 | rep_write(sd, 0x76, spa_loc & 0xff); | 1939 | |
1799 | rep_write_and_or(sd, 0x77, 0xbf, (spa_loc >> 2) & 0x40); | 1940 | if (info->type == ADV7604) { |
1941 | rep_write(sd, 0x76, spa_loc & 0xff); | ||
1942 | rep_write_and_or(sd, 0x77, 0xbf, (spa_loc & 0x100) >> 2); | ||
1943 | } else { | ||
1944 | /* FIXME: Where is the SPA location LSB register ? */ | ||
1945 | rep_write_and_or(sd, 0x71, 0xfe, (spa_loc & 0x100) >> 8); | ||
1946 | } | ||
1800 | 1947 | ||
1801 | edid->edid[spa_loc] = state->spa_port_a[0]; | 1948 | edid->edid[spa_loc] = state->spa_port_a[0]; |
1802 | edid->edid[spa_loc + 1] = state->spa_port_a[1]; | 1949 | edid->edid[spa_loc + 1] = state->spa_port_a[1]; |
@@ -1815,10 +1962,10 @@ static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_edid *edid) | |||
1815 | 1962 | ||
1816 | /* adv7604 calculates the checksums and enables I2C access to internal | 1963 | /* adv7604 calculates the checksums and enables I2C access to internal |
1817 | EDID RAM from DDC port. */ | 1964 | EDID RAM from DDC port. */ |
1818 | rep_write_and_or(sd, 0x77, 0xf0, state->edid.present); | 1965 | rep_write_and_or(sd, info->edid_enable_reg, 0xf0, state->edid.present); |
1819 | 1966 | ||
1820 | for (i = 0; i < 1000; i++) { | 1967 | for (i = 0; i < 1000; i++) { |
1821 | if (rep_read(sd, 0x7d) & state->edid.present) | 1968 | if (rep_read(sd, info->edid_status_reg) & state->edid.present) |
1822 | break; | 1969 | break; |
1823 | mdelay(1); | 1970 | mdelay(1); |
1824 | } | 1971 | } |
@@ -1881,6 +2028,7 @@ static void print_avi_infoframe(struct v4l2_subdev *sd) | |||
1881 | static int adv7604_log_status(struct v4l2_subdev *sd) | 2028 | static int adv7604_log_status(struct v4l2_subdev *sd) |
1882 | { | 2029 | { |
1883 | struct adv7604_state *state = to_state(sd); | 2030 | struct adv7604_state *state = to_state(sd); |
2031 | const struct adv7604_chip_info *info = state->info; | ||
1884 | struct v4l2_dv_timings timings; | 2032 | struct v4l2_dv_timings timings; |
1885 | struct stdi_readback stdi; | 2033 | struct stdi_readback stdi; |
1886 | u8 reg_io_0x02 = io_read(sd, 0x02); | 2034 | u8 reg_io_0x02 = io_read(sd, 0x02); |
@@ -1915,7 +2063,7 @@ static int adv7604_log_status(struct v4l2_subdev *sd) | |||
1915 | 2063 | ||
1916 | v4l2_info(sd, "-----Chip status-----\n"); | 2064 | v4l2_info(sd, "-----Chip status-----\n"); |
1917 | v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on"); | 2065 | v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on"); |
1918 | edid_enabled = rep_read(sd, 0x7d); | 2066 | edid_enabled = rep_read(sd, info->edid_status_reg); |
1919 | v4l2_info(sd, "EDID enabled port A: %s, B: %s, C: %s, D: %s\n", | 2067 | v4l2_info(sd, "EDID enabled port A: %s, B: %s, C: %s, D: %s\n", |
1920 | ((edid_enabled & 0x01) ? "Yes" : "No"), | 2068 | ((edid_enabled & 0x01) ? "Yes" : "No"), |
1921 | ((edid_enabled & 0x02) ? "Yes" : "No"), | 2069 | ((edid_enabled & 0x02) ? "Yes" : "No"), |
@@ -1925,12 +2073,12 @@ static int adv7604_log_status(struct v4l2_subdev *sd) | |||
1925 | "enabled" : "disabled"); | 2073 | "enabled" : "disabled"); |
1926 | 2074 | ||
1927 | v4l2_info(sd, "-----Signal status-----\n"); | 2075 | v4l2_info(sd, "-----Signal status-----\n"); |
1928 | cable_det = io_read(sd, 0x6f); | 2076 | cable_det = info->read_cable_det(sd); |
1929 | v4l2_info(sd, "Cable detected (+5V power) port A: %s, B: %s, C: %s, D: %s\n", | 2077 | v4l2_info(sd, "Cable detected (+5V power) port A: %s, B: %s, C: %s, D: %s\n", |
1930 | ((cable_det & 0x10) ? "Yes" : "No"), | 2078 | ((cable_det & 0x01) ? "Yes" : "No"), |
1931 | ((cable_det & 0x08) ? "Yes" : "No"), | 2079 | ((cable_det & 0x02) ? "Yes" : "No"), |
1932 | ((cable_det & 0x04) ? "Yes" : "No"), | 2080 | ((cable_det & 0x04) ? "Yes" : "No"), |
1933 | ((cable_det & 0x02) ? "Yes" : "No")); | 2081 | ((cable_det & 0x08) ? "Yes" : "No")); |
1934 | v4l2_info(sd, "TMDS signal detected: %s\n", | 2082 | v4l2_info(sd, "TMDS signal detected: %s\n", |
1935 | no_signal_tmds(sd) ? "false" : "true"); | 2083 | no_signal_tmds(sd) ? "false" : "true"); |
1936 | v4l2_info(sd, "TMDS signal locked: %s\n", | 2084 | v4l2_info(sd, "TMDS signal locked: %s\n", |
@@ -2103,6 +2251,7 @@ static const struct v4l2_ctrl_config adv7604_ctrl_free_run_color = { | |||
2103 | static int adv7604_core_init(struct v4l2_subdev *sd) | 2251 | static int adv7604_core_init(struct v4l2_subdev *sd) |
2104 | { | 2252 | { |
2105 | struct adv7604_state *state = to_state(sd); | 2253 | struct adv7604_state *state = to_state(sd); |
2254 | const struct adv7604_chip_info *info = state->info; | ||
2106 | struct adv7604_platform_data *pdata = &state->pdata; | 2255 | struct adv7604_platform_data *pdata = &state->pdata; |
2107 | 2256 | ||
2108 | hdmi_write(sd, 0x48, | 2257 | hdmi_write(sd, 0x48, |
@@ -2156,19 +2305,31 @@ static int adv7604_core_init(struct v4l2_subdev *sd) | |||
2156 | /* TODO from platform data */ | 2305 | /* TODO from platform data */ |
2157 | afe_write(sd, 0xb5, 0x01); /* Setting MCLK to 256Fs */ | 2306 | afe_write(sd, 0xb5, 0x01); /* Setting MCLK to 256Fs */ |
2158 | 2307 | ||
2159 | afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */ | 2308 | if (adv7604_has_afe(state)) { |
2160 | io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4); | 2309 | afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */ |
2310 | io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4); | ||
2311 | } | ||
2161 | 2312 | ||
2162 | /* interrupts */ | 2313 | /* interrupts */ |
2163 | io_write(sd, 0x40, 0xc2); /* Configure INT1 */ | 2314 | io_write(sd, 0x40, 0xc0 | pdata->int1_config); /* Configure INT1 */ |
2164 | io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */ | ||
2165 | io_write(sd, 0x46, 0x98); /* Enable SSPD, STDI and CP unlocked interrupts */ | 2315 | io_write(sd, 0x46, 0x98); /* Enable SSPD, STDI and CP unlocked interrupts */ |
2166 | io_write(sd, 0x6e, 0xc1); /* Enable V_LOCKED, DE_REGEN_LCK, HDMI_MODE interrupts */ | 2316 | io_write(sd, 0x6e, info->fmt_change_digital_mask); /* Enable V_LOCKED and DE_REGEN_LCK interrupts */ |
2167 | io_write(sd, 0x73, 0x1e); /* Enable CABLE_DET_A_ST (+5v) interrupts */ | 2317 | io_write(sd, 0x73, info->cable_det_mask); /* Enable cable detection (+5v) interrupts */ |
2318 | info->setup_irqs(sd); | ||
2168 | 2319 | ||
2169 | return v4l2_ctrl_handler_setup(sd->ctrl_handler); | 2320 | return v4l2_ctrl_handler_setup(sd->ctrl_handler); |
2170 | } | 2321 | } |
2171 | 2322 | ||
2323 | static void adv7604_setup_irqs(struct v4l2_subdev *sd) | ||
2324 | { | ||
2325 | io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */ | ||
2326 | } | ||
2327 | |||
2328 | static void adv7611_setup_irqs(struct v4l2_subdev *sd) | ||
2329 | { | ||
2330 | io_write(sd, 0x41, 0xd0); /* STDI irq for any change, disable INT2 */ | ||
2331 | } | ||
2332 | |||
2172 | static void adv7604_unregister_clients(struct adv7604_state *state) | 2333 | static void adv7604_unregister_clients(struct adv7604_state *state) |
2173 | { | 2334 | { |
2174 | if (state->i2c_avlink) | 2335 | if (state->i2c_avlink) |
@@ -2207,6 +2368,130 @@ static struct i2c_client *adv7604_dummy_client(struct v4l2_subdev *sd, | |||
2207 | return i2c_new_dummy(client->adapter, io_read(sd, io_reg) >> 1); | 2368 | return i2c_new_dummy(client->adapter, io_read(sd, io_reg) >> 1); |
2208 | } | 2369 | } |
2209 | 2370 | ||
2371 | static const struct adv7604_reg_seq adv7604_recommended_settings_afe[] = { | ||
2372 | /* reset ADI recommended settings for HDMI: */ | ||
2373 | /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */ | ||
2374 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x0d), 0x04 }, /* HDMI filter optimization */ | ||
2375 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x0d), 0x04 }, /* HDMI filter optimization */ | ||
2376 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x3d), 0x00 }, /* DDC bus active pull-up control */ | ||
2377 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x3e), 0x74 }, /* TMDS PLL optimization */ | ||
2378 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x4e), 0x3b }, /* TMDS PLL optimization */ | ||
2379 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0x74 }, /* TMDS PLL optimization */ | ||
2380 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x63 }, /* TMDS PLL optimization */ | ||
2381 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8d), 0x18 }, /* equaliser */ | ||
2382 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8e), 0x34 }, /* equaliser */ | ||
2383 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x93), 0x88 }, /* equaliser */ | ||
2384 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x94), 0x2e }, /* equaliser */ | ||
2385 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x96), 0x00 }, /* enable automatic EQ changing */ | ||
2386 | |||
2387 | /* set ADI recommended settings for digitizer */ | ||
2388 | /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */ | ||
2389 | { ADV7604_REG(ADV7604_PAGE_AFE, 0x12), 0x7b }, /* ADC noise shaping filter controls */ | ||
2390 | { ADV7604_REG(ADV7604_PAGE_AFE, 0x0c), 0x1f }, /* CP core gain controls */ | ||
2391 | { ADV7604_REG(ADV7604_PAGE_CP, 0x3e), 0x04 }, /* CP core pre-gain control */ | ||
2392 | { ADV7604_REG(ADV7604_PAGE_CP, 0xc3), 0x39 }, /* CP coast control. Graphics mode */ | ||
2393 | { ADV7604_REG(ADV7604_PAGE_CP, 0x40), 0x5c }, /* CP core pre-gain control. Graphics mode */ | ||
2394 | |||
2395 | { ADV7604_REG_SEQ_TERM, 0 }, | ||
2396 | }; | ||
2397 | |||
2398 | static const struct adv7604_reg_seq adv7604_recommended_settings_hdmi[] = { | ||
2399 | /* set ADI recommended settings for HDMI: */ | ||
2400 | /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */ | ||
2401 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x0d), 0x84 }, /* HDMI filter optimization */ | ||
2402 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x3d), 0x10 }, /* DDC bus active pull-up control */ | ||
2403 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x3e), 0x39 }, /* TMDS PLL optimization */ | ||
2404 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x4e), 0x3b }, /* TMDS PLL optimization */ | ||
2405 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0xb6 }, /* TMDS PLL optimization */ | ||
2406 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x03 }, /* TMDS PLL optimization */ | ||
2407 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8d), 0x18 }, /* equaliser */ | ||
2408 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8e), 0x34 }, /* equaliser */ | ||
2409 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x93), 0x8b }, /* equaliser */ | ||
2410 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x94), 0x2d }, /* equaliser */ | ||
2411 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x96), 0x01 }, /* enable automatic EQ changing */ | ||
2412 | |||
2413 | /* reset ADI recommended settings for digitizer */ | ||
2414 | /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */ | ||
2415 | { ADV7604_REG(ADV7604_PAGE_AFE, 0x12), 0xfb }, /* ADC noise shaping filter controls */ | ||
2416 | { ADV7604_REG(ADV7604_PAGE_AFE, 0x0c), 0x0d }, /* CP core gain controls */ | ||
2417 | |||
2418 | { ADV7604_REG_SEQ_TERM, 0 }, | ||
2419 | }; | ||
2420 | |||
2421 | static const struct adv7604_reg_seq adv7611_recommended_settings_hdmi[] = { | ||
2422 | { ADV7604_REG(ADV7604_PAGE_CP, 0x6c), 0x00 }, | ||
2423 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x6f), 0x0c }, | ||
2424 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x87), 0x70 }, | ||
2425 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0xda }, | ||
2426 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x01 }, | ||
2427 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x03), 0x98 }, | ||
2428 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x4c), 0x44 }, | ||
2429 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8d), 0x04 }, | ||
2430 | { ADV7604_REG(ADV7604_PAGE_HDMI, 0x8e), 0x1e }, | ||
2431 | |||
2432 | { ADV7604_REG_SEQ_TERM, 0 }, | ||
2433 | }; | ||
2434 | |||
2435 | static const struct adv7604_chip_info adv7604_chip_info[] = { | ||
2436 | [ADV7604] = { | ||
2437 | .type = ADV7604, | ||
2438 | .has_afe = true, | ||
2439 | .max_port = ADV7604_INPUT_VGA_COMP, | ||
2440 | .num_dv_ports = 4, | ||
2441 | .edid_enable_reg = 0x77, | ||
2442 | .edid_status_reg = 0x7d, | ||
2443 | .lcf_reg = 0xb3, | ||
2444 | .tdms_lock_mask = 0xe0, | ||
2445 | .cable_det_mask = 0x1e, | ||
2446 | .fmt_change_digital_mask = 0xc1, | ||
2447 | .set_termination = adv7604_set_termination, | ||
2448 | .setup_irqs = adv7604_setup_irqs, | ||
2449 | .read_hdmi_pixelclock = adv7604_read_hdmi_pixelclock, | ||
2450 | .read_cable_det = adv7604_read_cable_det, | ||
2451 | .recommended_settings = { | ||
2452 | [0] = adv7604_recommended_settings_afe, | ||
2453 | [1] = adv7604_recommended_settings_hdmi, | ||
2454 | }, | ||
2455 | .num_recommended_settings = { | ||
2456 | [0] = ARRAY_SIZE(adv7604_recommended_settings_afe), | ||
2457 | [1] = ARRAY_SIZE(adv7604_recommended_settings_hdmi), | ||
2458 | }, | ||
2459 | .page_mask = BIT(ADV7604_PAGE_IO) | BIT(ADV7604_PAGE_AVLINK) | | ||
2460 | BIT(ADV7604_PAGE_CEC) | BIT(ADV7604_PAGE_INFOFRAME) | | ||
2461 | BIT(ADV7604_PAGE_ESDP) | BIT(ADV7604_PAGE_DPP) | | ||
2462 | BIT(ADV7604_PAGE_AFE) | BIT(ADV7604_PAGE_REP) | | ||
2463 | BIT(ADV7604_PAGE_EDID) | BIT(ADV7604_PAGE_HDMI) | | ||
2464 | BIT(ADV7604_PAGE_TEST) | BIT(ADV7604_PAGE_CP) | | ||
2465 | BIT(ADV7604_PAGE_VDP), | ||
2466 | }, | ||
2467 | [ADV7611] = { | ||
2468 | .type = ADV7611, | ||
2469 | .has_afe = false, | ||
2470 | .max_port = ADV7604_INPUT_HDMI_PORT_A, | ||
2471 | .num_dv_ports = 1, | ||
2472 | .edid_enable_reg = 0x74, | ||
2473 | .edid_status_reg = 0x76, | ||
2474 | .lcf_reg = 0xa3, | ||
2475 | .tdms_lock_mask = 0x43, | ||
2476 | .cable_det_mask = 0x01, | ||
2477 | .fmt_change_digital_mask = 0x03, | ||
2478 | .set_termination = adv7611_set_termination, | ||
2479 | .setup_irqs = adv7611_setup_irqs, | ||
2480 | .read_hdmi_pixelclock = adv7611_read_hdmi_pixelclock, | ||
2481 | .read_cable_det = adv7611_read_cable_det, | ||
2482 | .recommended_settings = { | ||
2483 | [1] = adv7611_recommended_settings_hdmi, | ||
2484 | }, | ||
2485 | .num_recommended_settings = { | ||
2486 | [1] = ARRAY_SIZE(adv7611_recommended_settings_hdmi), | ||
2487 | }, | ||
2488 | .page_mask = BIT(ADV7604_PAGE_IO) | BIT(ADV7604_PAGE_CEC) | | ||
2489 | BIT(ADV7604_PAGE_INFOFRAME) | BIT(ADV7604_PAGE_AFE) | | ||
2490 | BIT(ADV7604_PAGE_REP) | BIT(ADV7604_PAGE_EDID) | | ||
2491 | BIT(ADV7604_PAGE_HDMI) | BIT(ADV7604_PAGE_CP), | ||
2492 | }, | ||
2493 | }; | ||
2494 | |||
2210 | static int adv7604_probe(struct i2c_client *client, | 2495 | static int adv7604_probe(struct i2c_client *client, |
2211 | const struct i2c_device_id *id) | 2496 | const struct i2c_device_id *id) |
2212 | { | 2497 | { |
@@ -2216,6 +2501,7 @@ static int adv7604_probe(struct i2c_client *client, | |||
2216 | struct adv7604_platform_data *pdata = client->dev.platform_data; | 2501 | struct adv7604_platform_data *pdata = client->dev.platform_data; |
2217 | struct v4l2_ctrl_handler *hdl; | 2502 | struct v4l2_ctrl_handler *hdl; |
2218 | struct v4l2_subdev *sd; | 2503 | struct v4l2_subdev *sd; |
2504 | u16 val; | ||
2219 | int err; | 2505 | int err; |
2220 | 2506 | ||
2221 | /* Check if the adapter supports the needed features */ | 2507 | /* Check if the adapter supports the needed features */ |
@@ -2230,6 +2516,8 @@ static int adv7604_probe(struct i2c_client *client, | |||
2230 | return -ENOMEM; | 2516 | return -ENOMEM; |
2231 | } | 2517 | } |
2232 | 2518 | ||
2519 | state->info = &adv7604_chip_info[id->driver_data]; | ||
2520 | |||
2233 | /* initialize variables */ | 2521 | /* initialize variables */ |
2234 | state->restart_stdi_once = true; | 2522 | state->restart_stdi_once = true; |
2235 | state->selected_input = ~0; | 2523 | state->selected_input = ~0; |
@@ -2244,18 +2532,36 @@ static int adv7604_probe(struct i2c_client *client, | |||
2244 | 2532 | ||
2245 | sd = &state->sd; | 2533 | sd = &state->sd; |
2246 | v4l2_i2c_subdev_init(sd, client, &adv7604_ops); | 2534 | v4l2_i2c_subdev_init(sd, client, &adv7604_ops); |
2535 | snprintf(sd->name, sizeof(sd->name), "%s %d-%04x", | ||
2536 | id->name, i2c_adapter_id(client->adapter), | ||
2537 | client->addr); | ||
2247 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; | 2538 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
2248 | 2539 | ||
2249 | /* i2c access to adv7604? */ | 2540 | /* |
2250 | if (adv_smbus_read_byte_data_check(client, 0xfb, false) != 0x68) { | 2541 | * Verify that the chip is present. On ADV7604 the RD_INFO register only |
2251 | v4l2_info(sd, "not an adv7604 on address 0x%x\n", | 2542 | * identifies the revision, while on ADV7611 it identifies the model as |
2252 | client->addr << 1); | 2543 | * well. Use the HDMI slave address on ADV7604 and RD_INFO on ADV7611. |
2253 | return -ENODEV; | 2544 | */ |
2545 | if (state->info->type == ADV7604) { | ||
2546 | val = adv_smbus_read_byte_data_check(client, 0xfb, false); | ||
2547 | if (val != 0x68) { | ||
2548 | v4l2_info(sd, "not an adv7604 on address 0x%x\n", | ||
2549 | client->addr << 1); | ||
2550 | return -ENODEV; | ||
2551 | } | ||
2552 | } else { | ||
2553 | val = (adv_smbus_read_byte_data_check(client, 0xea, false) << 8) | ||
2554 | | (adv_smbus_read_byte_data_check(client, 0xeb, false) << 0); | ||
2555 | if (val != 0x2051) { | ||
2556 | v4l2_info(sd, "not an adv7611 on address 0x%x\n", | ||
2557 | client->addr << 1); | ||
2558 | return -ENODEV; | ||
2559 | } | ||
2254 | } | 2560 | } |
2255 | 2561 | ||
2256 | /* control handlers */ | 2562 | /* control handlers */ |
2257 | hdl = &state->hdl; | 2563 | hdl = &state->hdl; |
2258 | v4l2_ctrl_handler_init(hdl, 9); | 2564 | v4l2_ctrl_handler_init(hdl, adv7604_has_afe(state) ? 9 : 8); |
2259 | 2565 | ||
2260 | v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops, | 2566 | v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops, |
2261 | V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); | 2567 | V4L2_CID_BRIGHTNESS, -128, 127, 1, 0); |
@@ -2268,15 +2574,17 @@ static int adv7604_probe(struct i2c_client *client, | |||
2268 | 2574 | ||
2269 | /* private controls */ | 2575 | /* private controls */ |
2270 | state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, | 2576 | state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL, |
2271 | V4L2_CID_DV_RX_POWER_PRESENT, 0, 0x0f, 0, 0); | 2577 | V4L2_CID_DV_RX_POWER_PRESENT, 0, |
2578 | (1 << state->info->num_dv_ports) - 1, 0, 0); | ||
2272 | state->rgb_quantization_range_ctrl = | 2579 | state->rgb_quantization_range_ctrl = |
2273 | v4l2_ctrl_new_std_menu(hdl, &adv7604_ctrl_ops, | 2580 | v4l2_ctrl_new_std_menu(hdl, &adv7604_ctrl_ops, |
2274 | V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, | 2581 | V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL, |
2275 | 0, V4L2_DV_RGB_RANGE_AUTO); | 2582 | 0, V4L2_DV_RGB_RANGE_AUTO); |
2276 | 2583 | ||
2277 | /* custom controls */ | 2584 | /* custom controls */ |
2278 | state->analog_sampling_phase_ctrl = | 2585 | if (adv7604_has_afe(state)) |
2279 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL); | 2586 | state->analog_sampling_phase_ctrl = |
2587 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL); | ||
2280 | state->free_run_color_manual_ctrl = | 2588 | state->free_run_color_manual_ctrl = |
2281 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color_manual, NULL); | 2589 | v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color_manual, NULL); |
2282 | state->free_run_color_ctrl = | 2590 | state->free_run_color_ctrl = |
@@ -2289,7 +2597,8 @@ static int adv7604_probe(struct i2c_client *client, | |||
2289 | } | 2597 | } |
2290 | state->detect_tx_5v_ctrl->is_private = true; | 2598 | state->detect_tx_5v_ctrl->is_private = true; |
2291 | state->rgb_quantization_range_ctrl->is_private = true; | 2599 | state->rgb_quantization_range_ctrl->is_private = true; |
2292 | state->analog_sampling_phase_ctrl->is_private = true; | 2600 | if (adv7604_has_afe(state)) |
2601 | state->analog_sampling_phase_ctrl->is_private = true; | ||
2293 | state->free_run_color_manual_ctrl->is_private = true; | 2602 | state->free_run_color_manual_ctrl->is_private = true; |
2294 | state->free_run_color_ctrl->is_private = true; | 2603 | state->free_run_color_ctrl->is_private = true; |
2295 | 2604 | ||
@@ -2298,27 +2607,34 @@ static int adv7604_probe(struct i2c_client *client, | |||
2298 | goto err_hdl; | 2607 | goto err_hdl; |
2299 | } | 2608 | } |
2300 | 2609 | ||
2301 | state->i2c_avlink = adv7604_dummy_client(sd, pdata->i2c_avlink, 0xf3); | ||
2302 | state->i2c_cec = adv7604_dummy_client(sd, pdata->i2c_cec, 0xf4); | 2610 | state->i2c_cec = adv7604_dummy_client(sd, pdata->i2c_cec, 0xf4); |
2303 | state->i2c_infoframe = adv7604_dummy_client(sd, pdata->i2c_infoframe, 0xf5); | 2611 | state->i2c_infoframe = adv7604_dummy_client(sd, pdata->i2c_infoframe, 0xf5); |
2304 | state->i2c_esdp = adv7604_dummy_client(sd, pdata->i2c_esdp, 0xf6); | ||
2305 | state->i2c_dpp = adv7604_dummy_client(sd, pdata->i2c_dpp, 0xf7); | ||
2306 | state->i2c_afe = adv7604_dummy_client(sd, pdata->i2c_afe, 0xf8); | 2612 | state->i2c_afe = adv7604_dummy_client(sd, pdata->i2c_afe, 0xf8); |
2307 | state->i2c_repeater = adv7604_dummy_client(sd, pdata->i2c_repeater, 0xf9); | 2613 | state->i2c_repeater = adv7604_dummy_client(sd, pdata->i2c_repeater, 0xf9); |
2308 | state->i2c_edid = adv7604_dummy_client(sd, pdata->i2c_edid, 0xfa); | 2614 | state->i2c_edid = adv7604_dummy_client(sd, pdata->i2c_edid, 0xfa); |
2309 | state->i2c_hdmi = adv7604_dummy_client(sd, pdata->i2c_hdmi, 0xfb); | 2615 | state->i2c_hdmi = adv7604_dummy_client(sd, pdata->i2c_hdmi, 0xfb); |
2310 | state->i2c_test = adv7604_dummy_client(sd, pdata->i2c_test, 0xfc); | ||
2311 | state->i2c_cp = adv7604_dummy_client(sd, pdata->i2c_cp, 0xfd); | 2616 | state->i2c_cp = adv7604_dummy_client(sd, pdata->i2c_cp, 0xfd); |
2312 | state->i2c_vdp = adv7604_dummy_client(sd, pdata->i2c_vdp, 0xfe); | 2617 | if (!state->i2c_cec || !state->i2c_infoframe || !state->i2c_afe || |
2313 | if (!state->i2c_avlink || !state->i2c_cec || !state->i2c_infoframe || | ||
2314 | !state->i2c_esdp || !state->i2c_dpp || !state->i2c_afe || | ||
2315 | !state->i2c_repeater || !state->i2c_edid || !state->i2c_hdmi || | 2618 | !state->i2c_repeater || !state->i2c_edid || !state->i2c_hdmi || |
2316 | !state->i2c_test || !state->i2c_cp || !state->i2c_vdp) { | 2619 | !state->i2c_cp) { |
2317 | err = -ENOMEM; | 2620 | err = -ENOMEM; |
2318 | v4l2_err(sd, "failed to create all i2c clients\n"); | 2621 | v4l2_err(sd, "failed to create digital i2c clients\n"); |
2319 | goto err_i2c; | 2622 | goto err_i2c; |
2320 | } | 2623 | } |
2321 | 2624 | ||
2625 | if (adv7604_has_afe(state)) { | ||
2626 | state->i2c_avlink = adv7604_dummy_client(sd, pdata->i2c_avlink, 0xf3); | ||
2627 | state->i2c_esdp = adv7604_dummy_client(sd, pdata->i2c_esdp, 0xf6); | ||
2628 | state->i2c_dpp = adv7604_dummy_client(sd, pdata->i2c_dpp, 0xf7); | ||
2629 | state->i2c_test = adv7604_dummy_client(sd, pdata->i2c_test, 0xfc); | ||
2630 | state->i2c_vdp = adv7604_dummy_client(sd, pdata->i2c_vdp, 0xfe); | ||
2631 | if (!state->i2c_avlink || !state->i2c_esdp || !state->i2c_dpp || | ||
2632 | !state->i2c_test || !state->i2c_vdp) { | ||
2633 | err = -ENOMEM; | ||
2634 | v4l2_err(sd, "failed to create analog i2c clients\n"); | ||
2635 | goto err_i2c; | ||
2636 | } | ||
2637 | } | ||
2322 | /* work queues */ | 2638 | /* work queues */ |
2323 | state->work_queues = create_singlethread_workqueue(client->name); | 2639 | state->work_queues = create_singlethread_workqueue(client->name); |
2324 | if (!state->work_queues) { | 2640 | if (!state->work_queues) { |
@@ -2379,7 +2695,8 @@ static int adv7604_remove(struct i2c_client *client) | |||
2379 | /* ----------------------------------------------------------------------- */ | 2695 | /* ----------------------------------------------------------------------- */ |
2380 | 2696 | ||
2381 | static struct i2c_device_id adv7604_id[] = { | 2697 | static struct i2c_device_id adv7604_id[] = { |
2382 | { "adv7604", 0 }, | 2698 | { "adv7604", ADV7604 }, |
2699 | { "adv7611", ADV7611 }, | ||
2383 | { } | 2700 | { } |
2384 | }; | 2701 | }; |
2385 | MODULE_DEVICE_TABLE(i2c, adv7604_id); | 2702 | MODULE_DEVICE_TABLE(i2c, adv7604_id); |
diff --git a/include/media/adv7604.h b/include/media/adv7604.h index c6b39372eed7..b2500baee8ed 100644 --- a/include/media/adv7604.h +++ b/include/media/adv7604.h | |||
@@ -86,6 +86,13 @@ enum adv7604_drive_strength { | |||
86 | ADV7604_DR_STR_HIGH = 3, | 86 | ADV7604_DR_STR_HIGH = 3, |
87 | }; | 87 | }; |
88 | 88 | ||
89 | enum adv7604_int1_config { | ||
90 | ADV7604_INT1_CONFIG_OPEN_DRAIN, | ||
91 | ADV7604_INT1_CONFIG_ACTIVE_LOW, | ||
92 | ADV7604_INT1_CONFIG_ACTIVE_HIGH, | ||
93 | ADV7604_INT1_CONFIG_DISABLED, | ||
94 | }; | ||
95 | |||
89 | /* Platform dependent definition */ | 96 | /* Platform dependent definition */ |
90 | struct adv7604_platform_data { | 97 | struct adv7604_platform_data { |
91 | /* DIS_PWRDNB: 1 if the PWRDNB pin is unused and unconnected */ | 98 | /* DIS_PWRDNB: 1 if the PWRDNB pin is unused and unconnected */ |
@@ -103,6 +110,9 @@ struct adv7604_platform_data { | |||
103 | /* Select output format */ | 110 | /* Select output format */ |
104 | enum adv7604_op_format_sel op_format_sel; | 111 | enum adv7604_op_format_sel op_format_sel; |
105 | 112 | ||
113 | /* Configuration of the INT1 pin */ | ||
114 | enum adv7604_int1_config int1_config; | ||
115 | |||
106 | /* IO register 0x02 */ | 116 | /* IO register 0x02 */ |
107 | unsigned alt_gamma:1; | 117 | unsigned alt_gamma:1; |
108 | unsigned op_656_range:1; | 118 | unsigned op_656_range:1; |