Lines Matching +full:ddc +full:- +full:i2c +full:- +full:bus
1 // SPDX-License-Identifier: GPL-2.0-only
8 #include <linux/i2c.h>
65 static inline void sif_set_bit(struct mtk_hdmi_ddc *ddc, unsigned int offset, in sif_set_bit() argument
68 writel(readl(ddc->regs + offset) | val, ddc->regs + offset); in sif_set_bit()
71 static inline void sif_clr_bit(struct mtk_hdmi_ddc *ddc, unsigned int offset, in sif_clr_bit() argument
74 writel(readl(ddc->regs + offset) & ~val, ddc->regs + offset); in sif_clr_bit()
77 static inline bool sif_bit_is_set(struct mtk_hdmi_ddc *ddc, unsigned int offset, in sif_bit_is_set() argument
80 return (readl(ddc->regs + offset) & val) == val; in sif_bit_is_set()
83 static inline void sif_write_mask(struct mtk_hdmi_ddc *ddc, unsigned int offset, in sif_write_mask() argument
89 tmp = readl(ddc->regs + offset); in sif_write_mask()
92 writel(tmp, ddc->regs + offset); in sif_write_mask()
95 static inline unsigned int sif_read_mask(struct mtk_hdmi_ddc *ddc, in sif_read_mask() argument
99 return (readl(ddc->regs + offset) & mask) >> shift; in sif_read_mask()
102 static void ddcm_trigger_mode(struct mtk_hdmi_ddc *ddc, int mode) in ddcm_trigger_mode() argument
106 sif_write_mask(ddc, DDC_DDCMCTL1, DDCM_SIF_MODE_MASK, in ddcm_trigger_mode()
108 sif_set_bit(ddc, DDC_DDCMCTL1, DDCM_TRI); in ddcm_trigger_mode()
109 readl_poll_timeout(ddc->regs + DDC_DDCMCTL1, val, in ddcm_trigger_mode()
113 static int mtk_hdmi_ddc_read_msg(struct mtk_hdmi_ddc *ddc, struct i2c_msg *msg) in mtk_hdmi_ddc_read_msg() argument
115 struct device *dev = ddc->adap.dev.parent; in mtk_hdmi_ddc_read_msg()
121 ddcm_trigger_mode(ddc, DDCM_START); in mtk_hdmi_ddc_read_msg()
122 sif_write_mask(ddc, DDC_DDCMD0, 0xff, 0, (msg->addr << 1) | 0x01); in mtk_hdmi_ddc_read_msg()
123 sif_write_mask(ddc, DDC_DDCMCTL1, DDCM_PGLEN_MASK, DDCM_PGLEN_OFFSET, in mtk_hdmi_ddc_read_msg()
125 ddcm_trigger_mode(ddc, DDCM_WRITE_DATA); in mtk_hdmi_ddc_read_msg()
126 ack = sif_read_mask(ddc, DDC_DDCMCTL1, DDCM_ACK_MASK, DDCM_ACK_OFFSET); in mtk_hdmi_ddc_read_msg()
129 dev_err(dev, "i2c ack err!\n"); in mtk_hdmi_ddc_read_msg()
130 return -ENXIO; in mtk_hdmi_ddc_read_msg()
133 remain_count = msg->len; in mtk_hdmi_ddc_read_msg()
134 ack_count = (msg->len - 1) / 8; in mtk_hdmi_ddc_read_msg()
141 ack_count--; in mtk_hdmi_ddc_read_msg()
147 sif_write_mask(ddc, DDC_DDCMCTL1, DDCM_PGLEN_MASK, in mtk_hdmi_ddc_read_msg()
148 DDCM_PGLEN_OFFSET, read_count - 1); in mtk_hdmi_ddc_read_msg()
149 ddcm_trigger_mode(ddc, (ack_final == 1) ? in mtk_hdmi_ddc_read_msg()
153 ack = sif_read_mask(ddc, DDC_DDCMCTL1, DDCM_ACK_MASK, in mtk_hdmi_ddc_read_msg()
158 if (((ack_final == 1) && (temp_count != (read_count - 1))) || in mtk_hdmi_ddc_read_msg()
164 for (i = read_count; i >= 1; i--) { in mtk_hdmi_ddc_read_msg()
170 shift = (i - 5) * 8; in mtk_hdmi_ddc_read_msg()
173 shift = (i - 1) * 8; in mtk_hdmi_ddc_read_msg()
176 msg->buf[index + i - 1] = sif_read_mask(ddc, offset, in mtk_hdmi_ddc_read_msg()
181 remain_count -= read_count; in mtk_hdmi_ddc_read_msg()
188 static int mtk_hdmi_ddc_write_msg(struct mtk_hdmi_ddc *ddc, struct i2c_msg *msg) in mtk_hdmi_ddc_write_msg() argument
190 struct device *dev = ddc->adap.dev.parent; in mtk_hdmi_ddc_write_msg()
193 ddcm_trigger_mode(ddc, DDCM_START); in mtk_hdmi_ddc_write_msg()
194 sif_write_mask(ddc, DDC_DDCMD0, DDCM_DATA0, 0, msg->addr << 1); in mtk_hdmi_ddc_write_msg()
195 sif_write_mask(ddc, DDC_DDCMD0, DDCM_DATA1, 8, msg->buf[0]); in mtk_hdmi_ddc_write_msg()
196 sif_write_mask(ddc, DDC_DDCMCTL1, DDCM_PGLEN_MASK, DDCM_PGLEN_OFFSET, in mtk_hdmi_ddc_write_msg()
198 ddcm_trigger_mode(ddc, DDCM_WRITE_DATA); in mtk_hdmi_ddc_write_msg()
200 ack = sif_read_mask(ddc, DDC_DDCMCTL1, DDCM_ACK_MASK, DDCM_ACK_OFFSET); in mtk_hdmi_ddc_write_msg()
204 dev_err(dev, "i2c ack err!\n"); in mtk_hdmi_ddc_write_msg()
205 return -EIO; in mtk_hdmi_ddc_write_msg()
214 struct mtk_hdmi_ddc *ddc = adapter->algo_data; in mtk_hdmi_ddc_xfer() local
215 struct device *dev = adapter->dev.parent; in mtk_hdmi_ddc_xfer()
219 if (!ddc) { in mtk_hdmi_ddc_xfer()
221 return -EINVAL; in mtk_hdmi_ddc_xfer()
224 sif_set_bit(ddc, DDC_DDCMCTL0, DDCM_SCL_STRECH); in mtk_hdmi_ddc_xfer()
225 sif_set_bit(ddc, DDC_DDCMCTL0, DDCM_SM0EN); in mtk_hdmi_ddc_xfer()
226 sif_clr_bit(ddc, DDC_DDCMCTL0, DDCM_ODRAIN); in mtk_hdmi_ddc_xfer()
228 if (sif_bit_is_set(ddc, DDC_DDCMCTL1, DDCM_TRI)) { in mtk_hdmi_ddc_xfer()
229 dev_err(dev, "ddc line is busy!\n"); in mtk_hdmi_ddc_xfer()
230 return -EBUSY; in mtk_hdmi_ddc_xfer()
233 sif_write_mask(ddc, DDC_DDCMCTL0, DDCM_CLK_DIV_MASK, in mtk_hdmi_ddc_xfer()
239 dev_dbg(dev, "i2c msg, adr:0x%x, flags:%d, len :0x%x\n", in mtk_hdmi_ddc_xfer()
240 msg->addr, msg->flags, msg->len); in mtk_hdmi_ddc_xfer()
242 if (msg->flags & I2C_M_RD) in mtk_hdmi_ddc_xfer()
243 ret = mtk_hdmi_ddc_read_msg(ddc, msg); in mtk_hdmi_ddc_xfer()
245 ret = mtk_hdmi_ddc_write_msg(ddc, msg); in mtk_hdmi_ddc_xfer()
250 ddcm_trigger_mode(ddc, DDCM_STOP); in mtk_hdmi_ddc_xfer()
255 ddcm_trigger_mode(ddc, DDCM_STOP); in mtk_hdmi_ddc_xfer()
256 dev_err(dev, "ddc failed!\n"); in mtk_hdmi_ddc_xfer()
272 struct device *dev = &pdev->dev; in mtk_hdmi_ddc_probe()
273 struct mtk_hdmi_ddc *ddc; in mtk_hdmi_ddc_probe() local
277 ddc = devm_kzalloc(dev, sizeof(struct mtk_hdmi_ddc), GFP_KERNEL); in mtk_hdmi_ddc_probe()
278 if (!ddc) in mtk_hdmi_ddc_probe()
279 return -ENOMEM; in mtk_hdmi_ddc_probe()
281 ddc->clk = devm_clk_get(dev, "ddc-i2c"); in mtk_hdmi_ddc_probe()
282 if (IS_ERR(ddc->clk)) in mtk_hdmi_ddc_probe()
283 return dev_err_probe(dev, PTR_ERR(ddc->clk), in mtk_hdmi_ddc_probe()
286 ddc->regs = devm_platform_get_and_ioremap_resource(pdev, 0, &mem); in mtk_hdmi_ddc_probe()
287 if (IS_ERR(ddc->regs)) in mtk_hdmi_ddc_probe()
288 return PTR_ERR(ddc->regs); in mtk_hdmi_ddc_probe()
290 ret = clk_prepare_enable(ddc->clk); in mtk_hdmi_ddc_probe()
292 return dev_err_probe(dev, ret, "enable ddc clk failed!\n"); in mtk_hdmi_ddc_probe()
294 strscpy(ddc->adap.name, "mediatek-hdmi-ddc", sizeof(ddc->adap.name)); in mtk_hdmi_ddc_probe()
295 ddc->adap.owner = THIS_MODULE; in mtk_hdmi_ddc_probe()
296 ddc->adap.algo = &mtk_hdmi_ddc_algorithm; in mtk_hdmi_ddc_probe()
297 ddc->adap.retries = 3; in mtk_hdmi_ddc_probe()
298 ddc->adap.dev.of_node = dev->of_node; in mtk_hdmi_ddc_probe()
299 ddc->adap.algo_data = ddc; in mtk_hdmi_ddc_probe()
300 ddc->adap.dev.parent = &pdev->dev; in mtk_hdmi_ddc_probe()
302 ret = i2c_add_adapter(&ddc->adap); in mtk_hdmi_ddc_probe()
304 clk_disable_unprepare(ddc->clk); in mtk_hdmi_ddc_probe()
305 return dev_err_probe(dev, ret, "failed to add bus to i2c core\n"); in mtk_hdmi_ddc_probe()
308 platform_set_drvdata(pdev, ddc); in mtk_hdmi_ddc_probe()
310 dev_dbg(dev, "ddc->adap: %p\n", &ddc->adap); in mtk_hdmi_ddc_probe()
311 dev_dbg(dev, "ddc->clk: %p\n", ddc->clk); in mtk_hdmi_ddc_probe()
312 dev_dbg(dev, "physical adr: %pa, end: %pa\n", &mem->start, in mtk_hdmi_ddc_probe()
313 &mem->end); in mtk_hdmi_ddc_probe()
320 struct mtk_hdmi_ddc *ddc = platform_get_drvdata(pdev); in mtk_hdmi_ddc_remove() local
322 i2c_del_adapter(&ddc->adap); in mtk_hdmi_ddc_remove()
323 clk_disable_unprepare(ddc->clk); in mtk_hdmi_ddc_remove()
327 { .compatible = "mediatek,mt8173-hdmi-ddc", },
336 .name = "mediatek-hdmi-ddc",
342 MODULE_DESCRIPTION("MediaTek HDMI DDC Driver");