Lines Matching +full:stm32 +full:- +full:cec
1 // SPDX-License-Identifier: GPL-2.0
3 * STM32 CEC driver
17 #include <media/cec.h>
19 #define CEC_NAME "stm32-cec"
21 /* CEC registers */
80 static void cec_hw_init(struct stm32_cec *cec) in cec_hw_init() argument
82 regmap_update_bits(cec->regmap, CEC_CR, TXEOM | TXSOM | CECEN, 0); in cec_hw_init()
84 regmap_update_bits(cec->regmap, CEC_IER, ALL_TX_IT | ALL_RX_IT, in cec_hw_init()
87 regmap_update_bits(cec->regmap, CEC_CFGR, FULL_CFG, FULL_CFG); in cec_hw_init()
90 static void stm32_tx_done(struct stm32_cec *cec, u32 status) in stm32_tx_done() argument
93 cec_transmit_done(cec->adap, CEC_TX_STATUS_ERROR, in stm32_tx_done()
99 cec_transmit_done(cec->adap, CEC_TX_STATUS_ARB_LOST, in stm32_tx_done()
105 cec_transmit_done(cec->adap, CEC_TX_STATUS_NACK, in stm32_tx_done()
110 if (cec->irq_status & TXBR) { in stm32_tx_done()
112 if (cec->tx_cnt < cec->tx_msg.len) in stm32_tx_done()
113 regmap_write(cec->regmap, CEC_TXDR, in stm32_tx_done()
114 cec->tx_msg.msg[cec->tx_cnt++]); in stm32_tx_done()
117 if (cec->tx_cnt == cec->tx_msg.len) in stm32_tx_done()
118 regmap_update_bits(cec->regmap, CEC_CR, TXEOM, TXEOM); in stm32_tx_done()
121 if (cec->irq_status & TXEND) in stm32_tx_done()
122 cec_transmit_done(cec->adap, CEC_TX_STATUS_OK, 0, 0, 0, 0); in stm32_tx_done()
125 static void stm32_rx_done(struct stm32_cec *cec, u32 status) in stm32_rx_done() argument
127 if (cec->irq_status & (RXACKE | RXOVR)) { in stm32_rx_done()
128 cec->rx_msg.len = 0; in stm32_rx_done()
132 if (cec->irq_status & RXBR) { in stm32_rx_done()
135 regmap_read(cec->regmap, CEC_RXDR, &val); in stm32_rx_done()
136 cec->rx_msg.msg[cec->rx_msg.len++] = val & 0xFF; in stm32_rx_done()
139 if (cec->irq_status & RXEND) { in stm32_rx_done()
140 cec_received_msg(cec->adap, &cec->rx_msg); in stm32_rx_done()
141 cec->rx_msg.len = 0; in stm32_rx_done()
147 struct stm32_cec *cec = arg; in stm32_cec_irq_thread() local
149 if (cec->irq_status & ALL_TX_IT) in stm32_cec_irq_thread()
150 stm32_tx_done(cec, cec->irq_status); in stm32_cec_irq_thread()
152 if (cec->irq_status & ALL_RX_IT) in stm32_cec_irq_thread()
153 stm32_rx_done(cec, cec->irq_status); in stm32_cec_irq_thread()
155 cec->irq_status = 0; in stm32_cec_irq_thread()
162 struct stm32_cec *cec = arg; in stm32_cec_irq_handler() local
164 regmap_read(cec->regmap, CEC_ISR, &cec->irq_status); in stm32_cec_irq_handler()
166 regmap_update_bits(cec->regmap, CEC_ISR, in stm32_cec_irq_handler()
175 struct stm32_cec *cec = adap->priv; in stm32_cec_adap_enable() local
179 ret = clk_enable(cec->clk_cec); in stm32_cec_adap_enable()
181 dev_err(cec->dev, "fail to enable cec clock\n"); in stm32_cec_adap_enable()
183 clk_enable(cec->clk_hdmi_cec); in stm32_cec_adap_enable()
184 regmap_update_bits(cec->regmap, CEC_CR, CECEN, CECEN); in stm32_cec_adap_enable()
186 clk_disable(cec->clk_cec); in stm32_cec_adap_enable()
187 clk_disable(cec->clk_hdmi_cec); in stm32_cec_adap_enable()
188 regmap_update_bits(cec->regmap, CEC_CR, CECEN, 0); in stm32_cec_adap_enable()
196 struct stm32_cec *cec = adap->priv; in stm32_cec_adap_log_addr() local
201 regmap_read_poll_timeout(cec->regmap, CEC_CR, val, !(val & TXSOM), in stm32_cec_adap_log_addr()
203 regmap_update_bits(cec->regmap, CEC_CR, CECEN, 0); in stm32_cec_adap_log_addr()
206 regmap_update_bits(cec->regmap, CEC_CFGR, OAR, 0); in stm32_cec_adap_log_addr()
208 regmap_update_bits(cec->regmap, CEC_CFGR, oar, oar); in stm32_cec_adap_log_addr()
210 regmap_update_bits(cec->regmap, CEC_CR, CECEN, CECEN); in stm32_cec_adap_log_addr()
218 struct stm32_cec *cec = adap->priv; in stm32_cec_adap_transmit() local
221 cec->tx_msg = *msg; in stm32_cec_adap_transmit()
222 cec->tx_cnt = 0; in stm32_cec_adap_transmit()
225 * If the CEC message consists of only one byte, in stm32_cec_adap_transmit()
228 if (cec->tx_msg.len == 1) in stm32_cec_adap_transmit()
229 regmap_update_bits(cec->regmap, CEC_CR, TXEOM, TXEOM); in stm32_cec_adap_transmit()
232 regmap_update_bits(cec->regmap, CEC_CR, TXSOM, TXSOM); in stm32_cec_adap_transmit()
235 regmap_write(cec->regmap, CEC_TXDR, cec->tx_msg.msg[0]); in stm32_cec_adap_transmit()
236 cec->tx_cnt++; in stm32_cec_adap_transmit()
259 struct stm32_cec *cec; in stm32_cec_probe() local
263 cec = devm_kzalloc(&pdev->dev, sizeof(*cec), GFP_KERNEL); in stm32_cec_probe()
264 if (!cec) in stm32_cec_probe()
265 return -ENOMEM; in stm32_cec_probe()
267 cec->dev = &pdev->dev; in stm32_cec_probe()
270 mmio = devm_ioremap_resource(&pdev->dev, res); in stm32_cec_probe()
274 cec->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "cec", mmio, in stm32_cec_probe()
277 if (IS_ERR(cec->regmap)) in stm32_cec_probe()
278 return PTR_ERR(cec->regmap); in stm32_cec_probe()
280 cec->irq = platform_get_irq(pdev, 0); in stm32_cec_probe()
281 if (cec->irq < 0) in stm32_cec_probe()
282 return cec->irq; in stm32_cec_probe()
284 ret = devm_request_threaded_irq(&pdev->dev, cec->irq, in stm32_cec_probe()
288 pdev->name, cec); in stm32_cec_probe()
292 cec->clk_cec = devm_clk_get(&pdev->dev, "cec"); in stm32_cec_probe()
293 if (IS_ERR(cec->clk_cec)) { in stm32_cec_probe()
294 if (PTR_ERR(cec->clk_cec) != -EPROBE_DEFER) in stm32_cec_probe()
295 dev_err(&pdev->dev, "Cannot get cec clock\n"); in stm32_cec_probe()
297 return PTR_ERR(cec->clk_cec); in stm32_cec_probe()
300 ret = clk_prepare(cec->clk_cec); in stm32_cec_probe()
302 dev_err(&pdev->dev, "Unable to prepare cec clock\n"); in stm32_cec_probe()
306 cec->clk_hdmi_cec = devm_clk_get(&pdev->dev, "hdmi-cec"); in stm32_cec_probe()
307 if (IS_ERR(cec->clk_hdmi_cec) && in stm32_cec_probe()
308 PTR_ERR(cec->clk_hdmi_cec) == -EPROBE_DEFER) in stm32_cec_probe()
309 return -EPROBE_DEFER; in stm32_cec_probe()
311 if (!IS_ERR(cec->clk_hdmi_cec)) { in stm32_cec_probe()
312 ret = clk_prepare(cec->clk_hdmi_cec); in stm32_cec_probe()
314 dev_err(&pdev->dev, "Can't prepare hdmi-cec clock\n"); in stm32_cec_probe()
320 * CEC_CAP_PHYS_ADDR caps should be removed when a cec notifier is in stm32_cec_probe()
323 cec->adap = cec_allocate_adapter(&stm32_cec_adap_ops, cec, in stm32_cec_probe()
325 ret = PTR_ERR_OR_ZERO(cec->adap); in stm32_cec_probe()
329 ret = cec_register_adapter(cec->adap, &pdev->dev); in stm32_cec_probe()
331 cec_delete_adapter(cec->adap); in stm32_cec_probe()
335 cec_hw_init(cec); in stm32_cec_probe()
337 platform_set_drvdata(pdev, cec); in stm32_cec_probe()
344 struct stm32_cec *cec = platform_get_drvdata(pdev); in stm32_cec_remove() local
346 clk_unprepare(cec->clk_cec); in stm32_cec_remove()
347 clk_unprepare(cec->clk_hdmi_cec); in stm32_cec_remove()
349 cec_unregister_adapter(cec->adap); in stm32_cec_remove()
355 { .compatible = "st,stm32-cec" },
373 MODULE_DESCRIPTION("STMicroelectronics STM32 Consumer Electronics Control");