1.1 --- a/pkg/devices/lib/hdmi/src/jz4780.cc Sat May 23 16:05:22 2020 +0200
1.2 +++ b/pkg/devices/lib/hdmi/src/jz4780.cc Sat May 23 22:34:17 2020 +0200
1.3 @@ -96,17 +96,28 @@
1.4
1.5 I2c_phy_int_config0 = 0x3027, // PHY_I2CM_INT_ADDR
1.6 I2c_phy_int_config1 = 0x3028, // PHY_I2CM_CTLINT_ADDR
1.7 +
1.8 + // PHY registers.
1.9 +
1.10 + Phy_config = 0x3000, // PHY_CONF0
1.11 + Phy_test0 = 0x3001, // PHY_TST0
1.12 + Phy_test1 = 0x3002, // PHY_TST1
1.13 + Phy_test2 = 0x3003, // PHY_TST2
1.14 + Phy_status = 0x3004, // PHY_STAT0
1.15 + Phy_int_config = 0x3005, // PHY_INT0
1.16 + Phy_mask = 0x3006, // PHY_MASK0
1.17 + Phy_polarity = 0x3007, // PHY_POL0
1.18 };
1.19
1.20 // Identification values.
1.21
1.22 enum Product_id_values : unsigned
1.23 {
1.24 - Product_id0_transmitter = 0xa0, // PRODUCT_ID0_HDMI_TX
1.25 + Product_id0_transmitter = 0xa0, // PRODUCT_ID0_HDMI_TX
1.26
1.27 - Product_id1_hdcp = 0xc0, // PRODUCT_ID1_HDCP
1.28 - Product_id1_receiver = 0x02, // PRODUCT_ID1_HDMI_RX
1.29 - Product_id1_transmitter = 0x01, // PRODUCT_ID1_HDMI_TX
1.30 + Product_id1_hdcp = 0xc0, // PRODUCT_ID1_HDCP
1.31 + Product_id1_receiver = 0x02, // PRODUCT_ID1_HDMI_RX
1.32 + Product_id1_transmitter = 0x01, // PRODUCT_ID1_HDMI_TX
1.33 };
1.34
1.35 // Configuration values.
1.36 @@ -134,39 +145,86 @@
1.37
1.38 enum Int_mask_bits : unsigned
1.39 {
1.40 - Int_mask_wakeup = 0x2,
1.41 - Int_mask_all = 0x1,
1.42 + Int_mask_wakeup = 0x02,
1.43 + Int_mask_all = 0x01,
1.44 };
1.45
1.46 enum I2c_int_status_bits : unsigned
1.47 {
1.48 - I2c_int_status_done = 0x2,
1.49 - I2c_int_status_error = 0x1,
1.50 + I2c_int_status_done = 0x02,
1.51 + I2c_int_status_error = 0x01,
1.52 };
1.53
1.54 // I2C operation bits.
1.55
1.56 enum I2c_operation_bits : unsigned
1.57 {
1.58 - I2c_operation_write = 0x10,
1.59 - I2c_operation_segment_read = 0x2,
1.60 - I2c_operation_read = 0x1,
1.61 + I2c_operation_write = 0x10,
1.62 + I2c_operation_segment_read = 0x02,
1.63 + I2c_operation_read = 0x01,
1.64 };
1.65
1.66 // Interrupt configuration bits.
1.67
1.68 enum I2c_int_config0_bits : unsigned
1.69 {
1.70 - I2c_int_config_done_polarity = 0x8,
1.71 - I2c_int_config_done_mask = 0x4,
1.72 + I2c_int_config0_done_polarity = 0x08,
1.73 + I2c_int_config0_done_mask = 0x04,
1.74 };
1.75
1.76 enum I2c_int_config1_bits : unsigned
1.77 {
1.78 - I2c_int_config_nack_polarity = 0x80,
1.79 - I2c_int_config_nack_mask = 0x40,
1.80 - I2c_int_config_arb_polarity = 0x8,
1.81 - I2c_int_config_arb_mask = 0x4,
1.82 + I2c_int_config1_nack_polarity = 0x80,
1.83 + I2c_int_config1_nack_mask = 0x40,
1.84 + I2c_int_config1_arb_polarity = 0x08,
1.85 + I2c_int_config1_arb_mask = 0x04,
1.86 +};
1.87 +
1.88 +// PHY configuration values.
1.89 +
1.90 +enum Phy_config_bits : unsigned
1.91 +{
1.92 + Phy_config_pdz_mask = 0x80, // PHY_CONF0_PDZ_MASK
1.93 + Phy_config_enable_tmds_mask = 0x40, // PHY_CONF0_ENTMDS_MASK
1.94 + Phy_config_svsret_mask = 0x20, // PHY_CONF0_SVSRET_MASK
1.95 + Phy_config_gen2_pddq_mask = 0x10, // PHY_CONF0_GEN2_PDDQ_MASK
1.96 + Phy_config_gen2_tx_power_on_mask = 0x08, // PHY_CONF0_GEN2_TXPWRON_MASK
1.97 + Phy_config_gen2_enable_hotplug_detect_rx_sense_mask = 0x04, // PHY_CONF0_GEN2_ENHPDRXSENSE_MASK
1.98 + Phy_config_select_data_enable_polarity_mask = 0x02, // PHY_CONF0_SELDATAENPOL_MASK
1.99 + Phy_config_select_interface_control_mask = 0x01, // PHY_CONF0_SELDIPIF_MASK
1.100 +};
1.101 +
1.102 +enum Phy_test_bits : unsigned
1.103 +{
1.104 + Phy_test0_clear_mask = 0x20, // PHY_TST0_TSTCLR_MASK
1.105 + Phy_test0_enable_mask = 0x10, // PHY_TST0_TSTEN_MASK
1.106 + Phy_test0_clock_mask = 0x01, // PHY_TST0_TSTCLK_MASK
1.107 +};
1.108 +
1.109 +// PHY status and mask values.
1.110 +
1.111 +enum Phy_status_bits : unsigned
1.112 +{
1.113 + Phy_status_rx_sense_all = 0xf0,
1.114 + Phy_status_rx_sense3 = 0x80, // PHY_RX_SENSE3
1.115 + Phy_status_rx_sense2 = 0x40, // PHY_RX_SENSE2
1.116 + Phy_status_rx_sense1 = 0x20, // PHY_RX_SENSE1
1.117 + Phy_status_rx_sense0 = 0x10, // PHY_RX_SENSE0
1.118 + Phy_status_hotplug_detect = 0x02, // PHY_HPD
1.119 + Phy_status_tx_phy_lock = 0x01, // PHY_TX_PHY_LOCK
1.120 +};
1.121 +
1.122 +// PHY interrupt status and mask bits.
1.123 +
1.124 +enum Phy_int_status_bits : unsigned
1.125 +{
1.126 + Phy_int_status_rx_sense_all = 0x3c,
1.127 + Phy_int_status_rx_sense3 = 0x20, // IH_PHY_STAT0_RX_SENSE3
1.128 + Phy_int_status_rx_sense2 = 0x10, // IH_PHY_STAT0_RX_SENSE2
1.129 + Phy_int_status_rx_sense1 = 0x08, // IH_PHY_STAT0_RX_SENSE1
1.130 + Phy_int_status_rx_sense0 = 0x04, // IH_PHY_STAT0_RX_SENSE0
1.131 + Phy_int_status_tx_phy_lock = 0x02, // IH_PHY_STAT0_TX_PHY_LOCK
1.132 + Phy_int_status_hotplug_detect = 0x01, // IH_PHY_STAT0_HPD
1.133 };
1.134
1.135
1.136 @@ -185,8 +243,9 @@
1.137 _device_register = 0;
1.138
1.139 get_identification();
1.140 - int_init();
1.141 + irq_init();
1.142 i2c_init();
1.143 + hotplug_init();
1.144 }
1.145
1.146 void Hdmi_jz4780_chip::get_identification()
1.147 @@ -200,7 +259,7 @@
1.148 *minor = _version & 0xfff;
1.149 }
1.150
1.151 -void Hdmi_jz4780_chip::int_init()
1.152 +void Hdmi_jz4780_chip::irq_init()
1.153 {
1.154 // Disable interrupts.
1.155
1.156 @@ -226,11 +285,11 @@
1.157
1.158 void Hdmi_jz4780_chip::i2c_init()
1.159 {
1.160 - // Set PHY interrupt priorities.
1.161 + // Set PHY interrupt polarities.
1.162
1.163 - _regs[I2c_phy_int_config0] = I2c_int_config_done_polarity;
1.164 - _regs[I2c_phy_int_config1] = I2c_int_config_nack_polarity |
1.165 - I2c_int_config_arb_polarity;
1.166 + _regs[I2c_phy_int_config0] = I2c_int_config0_done_polarity;
1.167 + _regs[I2c_phy_int_config1] = I2c_int_config1_nack_polarity |
1.168 + I2c_int_config1_arb_polarity;
1.169
1.170 // Software reset.
1.171
1.172 @@ -242,9 +301,9 @@
1.173
1.174 // Set interrupt polarities.
1.175
1.176 - _regs[I2c_int_config0] = I2c_int_config_done_polarity;
1.177 - _regs[I2c_int_config1] = I2c_int_config_nack_polarity |
1.178 - I2c_int_config_arb_polarity;
1.179 + _regs[I2c_int_config0] = I2c_int_config0_done_polarity;
1.180 + _regs[I2c_int_config1] = I2c_int_config1_nack_polarity |
1.181 + I2c_int_config1_arb_polarity;
1.182
1.183 // Clear and mask/mute interrupts.
1.184
1.185 @@ -255,21 +314,29 @@
1.186 long Hdmi_jz4780_chip::i2c_wait()
1.187 {
1.188 long err;
1.189 + uint8_t int_status;
1.190 + l4_msgtag_t tag;
1.191
1.192 - // Wait for around 1s.
1.193 + do
1.194 + {
1.195 + tag = l4_irq_receive(_irq, L4_IPC_NEVER);
1.196
1.197 - l4_msgtag_t tag = l4_irq_receive(_irq, L4_IPC_NEVER);
1.198 + err = l4_ipc_error(tag, l4_utcb());
1.199 + if (err)
1.200 + return err;
1.201
1.202 - err = l4_ipc_error(tag, l4_utcb());
1.203 - if (err)
1.204 - return err;
1.205 + int_status = _regs[I2c_int_status];
1.206 +
1.207 + // Test for an error condition.
1.208
1.209 - // Test for an error condition.
1.210 + if (int_status & I2c_int_status_error)
1.211 + return -L4_EIO;
1.212
1.213 - if (_regs[I2c_int_status] & I2c_int_status_error)
1.214 - return -L4_EIO;
1.215 + // Acknowledge the interrupt.
1.216
1.217 - _regs[I2c_int_status] = _regs[I2c_int_status] | I2c_int_status_done;
1.218 + _regs[I2c_int_status] = int_status;
1.219 +
1.220 + } while (!(int_status & I2c_int_status_done));
1.221
1.222 return L4_EOK;
1.223 }
1.224 @@ -279,7 +346,7 @@
1.225 unsigned int i;
1.226 long err;
1.227
1.228 - // Clear interrupts.
1.229 + // Unmask interrupts.
1.230
1.231 _regs[I2c_int_mask] = 0;
1.232
1.233 @@ -327,6 +394,61 @@
1.234 _device_register = device_register;
1.235 }
1.236
1.237 +void Hdmi_jz4780_chip::hotplug_init()
1.238 +{
1.239 + // Set PHY interrupt polarities.
1.240 +
1.241 + _regs[Phy_polarity] = Phy_status_hotplug_detect | Phy_status_rx_sense_all;
1.242 +
1.243 + // Enable/unmask second-level interrupts.
1.244 +
1.245 + _regs[Phy_mask] = _regs[Phy_mask] & ~(Phy_status_hotplug_detect | Phy_status_rx_sense_all);
1.246 +
1.247 + // Clear pending interrupts.
1.248 +
1.249 + _regs[Phy_int_status] = Phy_int_status_hotplug_detect | Phy_int_status_rx_sense_all;
1.250 +
1.251 + // Enable/unmask interrupts.
1.252 +
1.253 + _regs[Phy_int_mask] = _regs[Phy_int_mask] & ~(Phy_int_status_hotplug_detect | Phy_int_status_rx_sense_all);
1.254 +}
1.255 +
1.256 +bool Hdmi_jz4780_chip::connected()
1.257 +{
1.258 + return (_regs[Phy_status] & Phy_status_hotplug_detect) != 0;
1.259 +}
1.260 +
1.261 +long Hdmi_jz4780_chip::wait_for_connection()
1.262 +{
1.263 + long err;
1.264 + uint8_t int_status, polarity;
1.265 + l4_msgtag_t tag;
1.266 +
1.267 + do
1.268 + {
1.269 + tag = l4_irq_receive(_irq, L4_IPC_NEVER);
1.270 +
1.271 + err = l4_ipc_error(tag, l4_utcb());
1.272 + if (err)
1.273 + return err;
1.274 +
1.275 + // Obtain the details.
1.276 +
1.277 + int_status = _regs[Phy_int_status];
1.278 + polarity = _regs[Phy_polarity];
1.279 +
1.280 + // Acknowledge the interrupt.
1.281 +
1.282 + _regs[Phy_int_status] = int_status;
1.283 +
1.284 + // Continue without a hotplug event indicating connection.
1.285 +
1.286 + } while (!((int_status & Phy_int_status_hotplug_detect) &&
1.287 + (polarity & Phy_status_hotplug_detect)));
1.288 +
1.289 + return L4_EOK;
1.290 +}
1.291 +
1.292
1.293
1.294 // C language interface functions.
1.295 @@ -360,3 +482,13 @@
1.296 {
1.297 static_cast<Hdmi_jz4780_chip *>(hdmi)->i2c_set_register(device_register);
1.298 }
1.299 +
1.300 +int jz4780_hdmi_connected(void *hdmi)
1.301 +{
1.302 + return (int) static_cast<Hdmi_jz4780_chip *>(hdmi)->connected();
1.303 +}
1.304 +
1.305 +long jz4780_hdmi_wait_for_connection(void *hdmi)
1.306 +{
1.307 + return static_cast<Hdmi_jz4780_chip *>(hdmi)->wait_for_connection();
1.308 +}