Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * adv7511_cec.c - Analog Devices ADV7511/33 cec driver
0004  *
0005  * Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
0006  */
0007 
0008 #include <linux/device.h>
0009 #include <linux/module.h>
0010 #include <linux/of_device.h>
0011 #include <linux/slab.h>
0012 #include <linux/clk.h>
0013 
0014 #include <media/cec.h>
0015 
0016 #include "adv7511.h"
0017 
0018 static const u8 ADV7511_REG_CEC_RX_FRAME_HDR[] = {
0019     ADV7511_REG_CEC_RX1_FRAME_HDR,
0020     ADV7511_REG_CEC_RX2_FRAME_HDR,
0021     ADV7511_REG_CEC_RX3_FRAME_HDR,
0022 };
0023 
0024 static const u8 ADV7511_REG_CEC_RX_FRAME_LEN[] = {
0025     ADV7511_REG_CEC_RX1_FRAME_LEN,
0026     ADV7511_REG_CEC_RX2_FRAME_LEN,
0027     ADV7511_REG_CEC_RX3_FRAME_LEN,
0028 };
0029 
0030 #define ADV7511_INT1_CEC_MASK \
0031     (ADV7511_INT1_CEC_TX_READY | ADV7511_INT1_CEC_TX_ARBIT_LOST | \
0032      ADV7511_INT1_CEC_TX_RETRY_TIMEOUT | ADV7511_INT1_CEC_RX_READY1 | \
0033      ADV7511_INT1_CEC_RX_READY2 | ADV7511_INT1_CEC_RX_READY3)
0034 
0035 static void adv_cec_tx_raw_status(struct adv7511 *adv7511, u8 tx_raw_status)
0036 {
0037     unsigned int offset = adv7511->reg_cec_offset;
0038     unsigned int val;
0039 
0040     if (regmap_read(adv7511->regmap_cec,
0041             ADV7511_REG_CEC_TX_ENABLE + offset, &val))
0042         return;
0043 
0044     if ((val & 0x01) == 0)
0045         return;
0046 
0047     if (tx_raw_status & ADV7511_INT1_CEC_TX_ARBIT_LOST) {
0048         cec_transmit_attempt_done(adv7511->cec_adap,
0049                       CEC_TX_STATUS_ARB_LOST);
0050         return;
0051     }
0052     if (tx_raw_status & ADV7511_INT1_CEC_TX_RETRY_TIMEOUT) {
0053         u8 status;
0054         u8 err_cnt = 0;
0055         u8 nack_cnt = 0;
0056         u8 low_drive_cnt = 0;
0057         unsigned int cnt;
0058 
0059         /*
0060          * We set this status bit since this hardware performs
0061          * retransmissions.
0062          */
0063         status = CEC_TX_STATUS_MAX_RETRIES;
0064         if (regmap_read(adv7511->regmap_cec,
0065                 ADV7511_REG_CEC_TX_LOW_DRV_CNT + offset, &cnt)) {
0066             err_cnt = 1;
0067             status |= CEC_TX_STATUS_ERROR;
0068         } else {
0069             nack_cnt = cnt & 0xf;
0070             if (nack_cnt)
0071                 status |= CEC_TX_STATUS_NACK;
0072             low_drive_cnt = cnt >> 4;
0073             if (low_drive_cnt)
0074                 status |= CEC_TX_STATUS_LOW_DRIVE;
0075         }
0076         cec_transmit_done(adv7511->cec_adap, status,
0077                   0, nack_cnt, low_drive_cnt, err_cnt);
0078         return;
0079     }
0080     if (tx_raw_status & ADV7511_INT1_CEC_TX_READY) {
0081         cec_transmit_attempt_done(adv7511->cec_adap, CEC_TX_STATUS_OK);
0082         return;
0083     }
0084 }
0085 
0086 static void adv7511_cec_rx(struct adv7511 *adv7511, int rx_buf)
0087 {
0088     unsigned int offset = adv7511->reg_cec_offset;
0089     struct cec_msg msg = {};
0090     unsigned int len;
0091     unsigned int val;
0092     u8 i;
0093 
0094     if (regmap_read(adv7511->regmap_cec,
0095             ADV7511_REG_CEC_RX_FRAME_LEN[rx_buf] + offset, &len))
0096         return;
0097 
0098     msg.len = len & 0x1f;
0099 
0100     if (msg.len > 16)
0101         msg.len = 16;
0102 
0103     if (!msg.len)
0104         return;
0105 
0106     for (i = 0; i < msg.len; i++) {
0107         regmap_read(adv7511->regmap_cec,
0108                 i + ADV7511_REG_CEC_RX_FRAME_HDR[rx_buf] + offset,
0109                 &val);
0110         msg.msg[i] = val;
0111     }
0112 
0113     /* Toggle RX Ready Clear bit to re-enable this RX buffer */
0114     regmap_update_bits(adv7511->regmap_cec,
0115                ADV7511_REG_CEC_RX_BUFFERS + offset, BIT(rx_buf),
0116                BIT(rx_buf));
0117     regmap_update_bits(adv7511->regmap_cec,
0118                ADV7511_REG_CEC_RX_BUFFERS + offset, BIT(rx_buf), 0);
0119 
0120     cec_received_msg(adv7511->cec_adap, &msg);
0121 }
0122 
0123 void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
0124 {
0125     unsigned int offset = adv7511->reg_cec_offset;
0126     const u32 irq_tx_mask = ADV7511_INT1_CEC_TX_READY |
0127                 ADV7511_INT1_CEC_TX_ARBIT_LOST |
0128                 ADV7511_INT1_CEC_TX_RETRY_TIMEOUT;
0129     const u32 irq_rx_mask = ADV7511_INT1_CEC_RX_READY1 |
0130                 ADV7511_INT1_CEC_RX_READY2 |
0131                 ADV7511_INT1_CEC_RX_READY3;
0132     unsigned int rx_status;
0133     int rx_order[3] = { -1, -1, -1 };
0134     int i;
0135 
0136     if (irq1 & irq_tx_mask)
0137         adv_cec_tx_raw_status(adv7511, irq1);
0138 
0139     if (!(irq1 & irq_rx_mask))
0140         return;
0141 
0142     if (regmap_read(adv7511->regmap_cec,
0143             ADV7511_REG_CEC_RX_STATUS + offset, &rx_status))
0144         return;
0145 
0146     /*
0147      * ADV7511_REG_CEC_RX_STATUS[5:0] contains the reception order of RX
0148      * buffers 0, 1, and 2 in bits [1:0], [3:2], and [5:4] respectively.
0149      * The values are to be interpreted as follows:
0150      *
0151      *   0 = buffer unused
0152      *   1 = buffer contains oldest received frame (if applicable)
0153      *   2 = buffer contains second oldest received frame (if applicable)
0154      *   3 = buffer contains third oldest received frame (if applicable)
0155      *
0156      * Fill rx_order with the sequence of RX buffer indices to
0157      * read from in order, where -1 indicates that there are no
0158      * more buffers to process.
0159      */
0160     for (i = 0; i < 3; i++) {
0161         unsigned int timestamp = (rx_status >> (2 * i)) & 0x3;
0162 
0163         if (timestamp)
0164             rx_order[timestamp - 1] = i;
0165     }
0166 
0167     /* Read CEC RX buffers in the appropriate order as prescribed above */
0168     for (i = 0; i < 3; i++) {
0169         int rx_buf = rx_order[i];
0170 
0171         if (rx_buf < 0)
0172             break;
0173 
0174         adv7511_cec_rx(adv7511, rx_buf);
0175     }
0176 }
0177 
0178 static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
0179 {
0180     struct adv7511 *adv7511 = cec_get_drvdata(adap);
0181     unsigned int offset = adv7511->reg_cec_offset;
0182 
0183     if (adv7511->i2c_cec == NULL)
0184         return -EIO;
0185 
0186     if (!adv7511->cec_enabled_adap && enable) {
0187         /* power up cec section */
0188         regmap_update_bits(adv7511->regmap_cec,
0189                    ADV7511_REG_CEC_CLK_DIV + offset,
0190                    0x03, 0x01);
0191         /* non-legacy mode and clear all rx buffers */
0192         regmap_write(adv7511->regmap_cec,
0193                  ADV7511_REG_CEC_RX_BUFFERS + offset, 0x0f);
0194         regmap_write(adv7511->regmap_cec,
0195                  ADV7511_REG_CEC_RX_BUFFERS + offset, 0x08);
0196         /* initially disable tx */
0197         regmap_update_bits(adv7511->regmap_cec,
0198                    ADV7511_REG_CEC_TX_ENABLE + offset, 1, 0);
0199         /* enabled irqs: */
0200         /* tx: ready */
0201         /* tx: arbitration lost */
0202         /* tx: retry timeout */
0203         /* rx: ready 1-3 */
0204         regmap_update_bits(adv7511->regmap,
0205                    ADV7511_REG_INT_ENABLE(1), 0x3f,
0206                    ADV7511_INT1_CEC_MASK);
0207     } else if (adv7511->cec_enabled_adap && !enable) {
0208         regmap_update_bits(adv7511->regmap,
0209                    ADV7511_REG_INT_ENABLE(1), 0x3f, 0);
0210         /* disable address mask 1-3 */
0211         regmap_update_bits(adv7511->regmap_cec,
0212                    ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
0213                    0x70, 0x00);
0214         /* power down cec section */
0215         regmap_update_bits(adv7511->regmap_cec,
0216                    ADV7511_REG_CEC_CLK_DIV + offset,
0217                    0x03, 0x00);
0218         adv7511->cec_valid_addrs = 0;
0219     }
0220     adv7511->cec_enabled_adap = enable;
0221     return 0;
0222 }
0223 
0224 static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
0225 {
0226     struct adv7511 *adv7511 = cec_get_drvdata(adap);
0227     unsigned int offset = adv7511->reg_cec_offset;
0228     unsigned int i, free_idx = ADV7511_MAX_ADDRS;
0229 
0230     if (!adv7511->cec_enabled_adap)
0231         return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO;
0232 
0233     if (addr == CEC_LOG_ADDR_INVALID) {
0234         regmap_update_bits(adv7511->regmap_cec,
0235                    ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
0236                    0x70, 0);
0237         adv7511->cec_valid_addrs = 0;
0238         return 0;
0239     }
0240 
0241     for (i = 0; i < ADV7511_MAX_ADDRS; i++) {
0242         bool is_valid = adv7511->cec_valid_addrs & (1 << i);
0243 
0244         if (free_idx == ADV7511_MAX_ADDRS && !is_valid)
0245             free_idx = i;
0246         if (is_valid && adv7511->cec_addr[i] == addr)
0247             return 0;
0248     }
0249     if (i == ADV7511_MAX_ADDRS) {
0250         i = free_idx;
0251         if (i == ADV7511_MAX_ADDRS)
0252             return -ENXIO;
0253     }
0254     adv7511->cec_addr[i] = addr;
0255     adv7511->cec_valid_addrs |= 1 << i;
0256 
0257     switch (i) {
0258     case 0:
0259         /* enable address mask 0 */
0260         regmap_update_bits(adv7511->regmap_cec,
0261                    ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
0262                    0x10, 0x10);
0263         /* set address for mask 0 */
0264         regmap_update_bits(adv7511->regmap_cec,
0265                    ADV7511_REG_CEC_LOG_ADDR_0_1 + offset,
0266                    0x0f, addr);
0267         break;
0268     case 1:
0269         /* enable address mask 1 */
0270         regmap_update_bits(adv7511->regmap_cec,
0271                    ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
0272                    0x20, 0x20);
0273         /* set address for mask 1 */
0274         regmap_update_bits(adv7511->regmap_cec,
0275                    ADV7511_REG_CEC_LOG_ADDR_0_1 + offset,
0276                    0xf0, addr << 4);
0277         break;
0278     case 2:
0279         /* enable address mask 2 */
0280         regmap_update_bits(adv7511->regmap_cec,
0281                    ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
0282                    0x40, 0x40);
0283         /* set address for mask 1 */
0284         regmap_update_bits(adv7511->regmap_cec,
0285                    ADV7511_REG_CEC_LOG_ADDR_2 + offset,
0286                    0x0f, addr);
0287         break;
0288     }
0289     return 0;
0290 }
0291 
0292 static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
0293                      u32 signal_free_time, struct cec_msg *msg)
0294 {
0295     struct adv7511 *adv7511 = cec_get_drvdata(adap);
0296     unsigned int offset = adv7511->reg_cec_offset;
0297     u8 len = msg->len;
0298     unsigned int i;
0299 
0300     /*
0301      * The number of retries is the number of attempts - 1, but retry
0302      * at least once. It's not clear if a value of 0 is allowed, so
0303      * let's do at least one retry.
0304      */
0305     regmap_update_bits(adv7511->regmap_cec,
0306                ADV7511_REG_CEC_TX_RETRY + offset,
0307                0x70, max(1, attempts - 1) << 4);
0308 
0309     /* blocking, clear cec tx irq status */
0310     regmap_update_bits(adv7511->regmap, ADV7511_REG_INT(1), 0x38, 0x38);
0311 
0312     /* write data */
0313     for (i = 0; i < len; i++)
0314         regmap_write(adv7511->regmap_cec,
0315                  i + ADV7511_REG_CEC_TX_FRAME_HDR + offset,
0316                  msg->msg[i]);
0317 
0318     /* set length (data + header) */
0319     regmap_write(adv7511->regmap_cec,
0320              ADV7511_REG_CEC_TX_FRAME_LEN + offset, len);
0321     /* start transmit, enable tx */
0322     regmap_write(adv7511->regmap_cec,
0323              ADV7511_REG_CEC_TX_ENABLE + offset, 0x01);
0324     return 0;
0325 }
0326 
0327 static const struct cec_adap_ops adv7511_cec_adap_ops = {
0328     .adap_enable = adv7511_cec_adap_enable,
0329     .adap_log_addr = adv7511_cec_adap_log_addr,
0330     .adap_transmit = adv7511_cec_adap_transmit,
0331 };
0332 
0333 static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511)
0334 {
0335     adv7511->cec_clk = devm_clk_get(dev, "cec");
0336     if (IS_ERR(adv7511->cec_clk)) {
0337         int ret = PTR_ERR(adv7511->cec_clk);
0338 
0339         adv7511->cec_clk = NULL;
0340         return ret;
0341     }
0342     clk_prepare_enable(adv7511->cec_clk);
0343     adv7511->cec_clk_freq = clk_get_rate(adv7511->cec_clk);
0344     return 0;
0345 }
0346 
0347 int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
0348 {
0349     unsigned int offset = adv7511->reg_cec_offset;
0350     int ret = adv7511_cec_parse_dt(dev, adv7511);
0351 
0352     if (ret)
0353         goto err_cec_parse_dt;
0354 
0355     adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
0356         adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS);
0357     if (IS_ERR(adv7511->cec_adap)) {
0358         ret = PTR_ERR(adv7511->cec_adap);
0359         goto err_cec_alloc;
0360     }
0361 
0362     regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0);
0363     /* cec soft reset */
0364     regmap_write(adv7511->regmap_cec,
0365              ADV7511_REG_CEC_SOFT_RESET + offset, 0x01);
0366     regmap_write(adv7511->regmap_cec,
0367              ADV7511_REG_CEC_SOFT_RESET + offset, 0x00);
0368 
0369     /* non-legacy mode - use all three RX buffers */
0370     regmap_write(adv7511->regmap_cec,
0371              ADV7511_REG_CEC_RX_BUFFERS + offset, 0x08);
0372 
0373     regmap_write(adv7511->regmap_cec,
0374              ADV7511_REG_CEC_CLK_DIV + offset,
0375              ((adv7511->cec_clk_freq / 750000) - 1) << 2);
0376 
0377     ret = cec_register_adapter(adv7511->cec_adap, dev);
0378     if (ret)
0379         goto err_cec_register;
0380     return 0;
0381 
0382 err_cec_register:
0383     cec_delete_adapter(adv7511->cec_adap);
0384     adv7511->cec_adap = NULL;
0385 err_cec_alloc:
0386     dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
0387          ret);
0388 err_cec_parse_dt:
0389     regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
0390              ADV7511_CEC_CTRL_POWER_DOWN);
0391     return ret == -EPROBE_DEFER ? ret : 0;
0392 }