0001
0002
0003
0004
0005
0006
0007 #include <linux/clk.h>
0008 #include <linux/i2c.h>
0009 #include <linux/iopoll.h>
0010
0011 #include "sun4i_hdmi.h"
0012
0013 #define SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK ( \
0014 SUN4I_HDMI_DDC_INT_STATUS_ILLEGAL_FIFO_OPERATION | \
0015 SUN4I_HDMI_DDC_INT_STATUS_DDC_RX_FIFO_UNDERFLOW | \
0016 SUN4I_HDMI_DDC_INT_STATUS_DDC_TX_FIFO_OVERFLOW | \
0017 SUN4I_HDMI_DDC_INT_STATUS_ARBITRATION_ERROR | \
0018 SUN4I_HDMI_DDC_INT_STATUS_ACK_ERROR | \
0019 SUN4I_HDMI_DDC_INT_STATUS_BUS_ERROR \
0020 )
0021
0022
0023 #define RX_THRESHOLD SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES_MAX
0024
0025 static int fifo_transfer(struct sun4i_hdmi *hdmi, u8 *buf, int len, bool read)
0026 {
0027
0028
0029
0030
0031 const unsigned long byte_time_ns = 100;
0032 const u32 mask = SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK |
0033 SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST |
0034 SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE;
0035 u32 reg;
0036
0037
0038
0039
0040 int read_len = RX_THRESHOLD +
0041 (hdmi->variant->ddc_fifo_thres_incl ? 0 : 1);
0042
0043
0044
0045
0046
0047 len = min_t(int, len, read ? read_len : SUN4I_HDMI_DDC_FIFO_SIZE);
0048
0049
0050 if (regmap_field_read_poll_timeout(hdmi->field_ddc_int_status, reg,
0051 reg & mask, len * byte_time_ns,
0052 100000))
0053 return -ETIMEDOUT;
0054
0055 if (reg & SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK)
0056 return -EIO;
0057
0058 if (read)
0059 ioread8_rep(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, len);
0060 else
0061 iowrite8_rep(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, len);
0062
0063
0064 regmap_field_force_write(hdmi->field_ddc_int_status,
0065 SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST);
0066
0067 return len;
0068 }
0069
0070 static int xfer_msg(struct sun4i_hdmi *hdmi, struct i2c_msg *msg)
0071 {
0072 int i, len;
0073 u32 reg;
0074
0075
0076 if (hdmi->variant->ddc_fifo_has_dir) {
0077 reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG);
0078 reg &= ~SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASK;
0079 reg |= (msg->flags & I2C_M_RD) ?
0080 SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ :
0081 SUN4I_HDMI_DDC_CTRL_FIFO_DIR_WRITE;
0082 writel(reg, hdmi->base + SUN4I_HDMI_DDC_CTRL_REG);
0083 }
0084
0085
0086 regmap_field_write(hdmi->field_ddc_addr_reg, 0);
0087
0088
0089 regmap_field_write(hdmi->field_ddc_slave_addr, msg->addr);
0090
0091
0092
0093
0094
0095
0096
0097 regmap_field_write(hdmi->field_ddc_fifo_tx_thres,
0098 hdmi->variant->ddc_fifo_thres_incl ? 0 : 1);
0099 regmap_field_write(hdmi->field_ddc_fifo_rx_thres, RX_THRESHOLD);
0100 regmap_field_write(hdmi->field_ddc_fifo_clear, 1);
0101 if (regmap_field_read_poll_timeout(hdmi->field_ddc_fifo_clear,
0102 reg, !reg, 100, 2000))
0103 return -EIO;
0104
0105
0106 regmap_field_write(hdmi->field_ddc_byte_count, msg->len);
0107
0108
0109 regmap_field_write(hdmi->field_ddc_cmd,
0110 msg->flags & I2C_M_RD ?
0111 SUN4I_HDMI_DDC_CMD_IMPLICIT_READ :
0112 SUN4I_HDMI_DDC_CMD_IMPLICIT_WRITE);
0113
0114
0115 regmap_field_force_write(hdmi->field_ddc_int_status,
0116 SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK |
0117 SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST |
0118 SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE);
0119
0120
0121 regmap_field_write(hdmi->field_ddc_start, 1);
0122
0123
0124 for (i = 0; i < msg->len; i += len) {
0125 len = fifo_transfer(hdmi, msg->buf + i, msg->len - i,
0126 msg->flags & I2C_M_RD);
0127 if (len <= 0)
0128 return len;
0129 }
0130
0131
0132 if (regmap_field_read_poll_timeout(hdmi->field_ddc_start,
0133 reg, !reg, 100, 100000))
0134 return -EIO;
0135
0136
0137 regmap_field_read(hdmi->field_ddc_int_status, ®);
0138 if ((reg & SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK) ||
0139 !(reg & SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE)) {
0140 return -EIO;
0141 }
0142
0143 return 0;
0144 }
0145
0146 static int sun4i_hdmi_i2c_xfer(struct i2c_adapter *adap,
0147 struct i2c_msg *msgs, int num)
0148 {
0149 struct sun4i_hdmi *hdmi = i2c_get_adapdata(adap);
0150 u32 reg;
0151 int err, i, ret = num;
0152
0153 for (i = 0; i < num; i++) {
0154 if (!msgs[i].len)
0155 return -EINVAL;
0156 if (msgs[i].len > SUN4I_HDMI_DDC_BYTE_COUNT_MAX)
0157 return -EINVAL;
0158 }
0159
0160
0161 clk_prepare_enable(hdmi->ddc_clk);
0162 clk_set_rate(hdmi->ddc_clk, 100000);
0163
0164
0165 regmap_field_write(hdmi->field_ddc_en, 1);
0166 regmap_field_write(hdmi->field_ddc_reset, 1);
0167 if (regmap_field_read_poll_timeout(hdmi->field_ddc_reset,
0168 reg, !reg, 100, 2000)) {
0169 clk_disable_unprepare(hdmi->ddc_clk);
0170 return -EIO;
0171 }
0172
0173 regmap_field_write(hdmi->field_ddc_sck_en, 1);
0174 regmap_field_write(hdmi->field_ddc_sda_en, 1);
0175
0176 for (i = 0; i < num; i++) {
0177 err = xfer_msg(hdmi, &msgs[i]);
0178 if (err) {
0179 ret = err;
0180 break;
0181 }
0182 }
0183
0184 clk_disable_unprepare(hdmi->ddc_clk);
0185 return ret;
0186 }
0187
0188 static u32 sun4i_hdmi_i2c_func(struct i2c_adapter *adap)
0189 {
0190 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
0191 }
0192
0193 static const struct i2c_algorithm sun4i_hdmi_i2c_algorithm = {
0194 .master_xfer = sun4i_hdmi_i2c_xfer,
0195 .functionality = sun4i_hdmi_i2c_func,
0196 };
0197
0198 static int sun4i_hdmi_init_regmap_fields(struct sun4i_hdmi *hdmi)
0199 {
0200 hdmi->field_ddc_en =
0201 devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0202 hdmi->variant->field_ddc_en);
0203 if (IS_ERR(hdmi->field_ddc_en))
0204 return PTR_ERR(hdmi->field_ddc_en);
0205
0206 hdmi->field_ddc_start =
0207 devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0208 hdmi->variant->field_ddc_start);
0209 if (IS_ERR(hdmi->field_ddc_start))
0210 return PTR_ERR(hdmi->field_ddc_start);
0211
0212 hdmi->field_ddc_reset =
0213 devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0214 hdmi->variant->field_ddc_reset);
0215 if (IS_ERR(hdmi->field_ddc_reset))
0216 return PTR_ERR(hdmi->field_ddc_reset);
0217
0218 hdmi->field_ddc_addr_reg =
0219 devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0220 hdmi->variant->field_ddc_addr_reg);
0221 if (IS_ERR(hdmi->field_ddc_addr_reg))
0222 return PTR_ERR(hdmi->field_ddc_addr_reg);
0223
0224 hdmi->field_ddc_slave_addr =
0225 devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0226 hdmi->variant->field_ddc_slave_addr);
0227 if (IS_ERR(hdmi->field_ddc_slave_addr))
0228 return PTR_ERR(hdmi->field_ddc_slave_addr);
0229
0230 hdmi->field_ddc_int_mask =
0231 devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0232 hdmi->variant->field_ddc_int_mask);
0233 if (IS_ERR(hdmi->field_ddc_int_mask))
0234 return PTR_ERR(hdmi->field_ddc_int_mask);
0235
0236 hdmi->field_ddc_int_status =
0237 devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0238 hdmi->variant->field_ddc_int_status);
0239 if (IS_ERR(hdmi->field_ddc_int_status))
0240 return PTR_ERR(hdmi->field_ddc_int_status);
0241
0242 hdmi->field_ddc_fifo_clear =
0243 devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0244 hdmi->variant->field_ddc_fifo_clear);
0245 if (IS_ERR(hdmi->field_ddc_fifo_clear))
0246 return PTR_ERR(hdmi->field_ddc_fifo_clear);
0247
0248 hdmi->field_ddc_fifo_rx_thres =
0249 devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0250 hdmi->variant->field_ddc_fifo_rx_thres);
0251 if (IS_ERR(hdmi->field_ddc_fifo_rx_thres))
0252 return PTR_ERR(hdmi->field_ddc_fifo_rx_thres);
0253
0254 hdmi->field_ddc_fifo_tx_thres =
0255 devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0256 hdmi->variant->field_ddc_fifo_tx_thres);
0257 if (IS_ERR(hdmi->field_ddc_fifo_tx_thres))
0258 return PTR_ERR(hdmi->field_ddc_fifo_tx_thres);
0259
0260 hdmi->field_ddc_byte_count =
0261 devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0262 hdmi->variant->field_ddc_byte_count);
0263 if (IS_ERR(hdmi->field_ddc_byte_count))
0264 return PTR_ERR(hdmi->field_ddc_byte_count);
0265
0266 hdmi->field_ddc_cmd =
0267 devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0268 hdmi->variant->field_ddc_cmd);
0269 if (IS_ERR(hdmi->field_ddc_cmd))
0270 return PTR_ERR(hdmi->field_ddc_cmd);
0271
0272 hdmi->field_ddc_sda_en =
0273 devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0274 hdmi->variant->field_ddc_sda_en);
0275 if (IS_ERR(hdmi->field_ddc_sda_en))
0276 return PTR_ERR(hdmi->field_ddc_sda_en);
0277
0278 hdmi->field_ddc_sck_en =
0279 devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
0280 hdmi->variant->field_ddc_sck_en);
0281 if (IS_ERR(hdmi->field_ddc_sck_en))
0282 return PTR_ERR(hdmi->field_ddc_sck_en);
0283
0284 return 0;
0285 }
0286
0287 int sun4i_hdmi_i2c_create(struct device *dev, struct sun4i_hdmi *hdmi)
0288 {
0289 struct i2c_adapter *adap;
0290 int ret = 0;
0291
0292 ret = sun4i_ddc_create(hdmi, hdmi->ddc_parent_clk);
0293 if (ret)
0294 return ret;
0295
0296 ret = sun4i_hdmi_init_regmap_fields(hdmi);
0297 if (ret)
0298 return ret;
0299
0300 adap = devm_kzalloc(dev, sizeof(*adap), GFP_KERNEL);
0301 if (!adap)
0302 return -ENOMEM;
0303
0304 adap->owner = THIS_MODULE;
0305 adap->class = I2C_CLASS_DDC;
0306 adap->algo = &sun4i_hdmi_i2c_algorithm;
0307 strlcpy(adap->name, "sun4i_hdmi_i2c adapter", sizeof(adap->name));
0308 i2c_set_adapdata(adap, hdmi);
0309
0310 ret = i2c_add_adapter(adap);
0311 if (ret)
0312 return ret;
0313
0314 hdmi->i2c = adap;
0315
0316 return ret;
0317 }