Lines Matching full:cec
3 * Designware HDMI CEC driver
19 #include <media/cec.h>
20 #include <media/cec-notifier.h>
22 #include "dw-hdmi-cec.h"
81 static void dw_hdmi_write(struct dw_hdmi_cec *cec, u8 val, int offset) in dw_hdmi_write() argument
83 cec->ops->write(cec->hdmi, val, offset); in dw_hdmi_write()
86 static u8 dw_hdmi_read(struct dw_hdmi_cec *cec, int offset) in dw_hdmi_read() argument
88 return cec->ops->read(cec->hdmi, offset); in dw_hdmi_read()
91 static void dw_hdmi_mod(struct dw_hdmi_cec *cec, unsigned int offset, u8 mask, u8 val) in dw_hdmi_mod() argument
93 cec->ops->mod(cec->hdmi, val, mask, offset); in dw_hdmi_mod()
98 struct dw_hdmi_cec *cec = cec_get_drvdata(adap); in dw_hdmi_cec_log_addr() local
101 cec->addresses = 0; in dw_hdmi_cec_log_addr()
103 cec->addresses |= BIT(logical_addr) | BIT(15); in dw_hdmi_cec_log_addr()
105 dw_hdmi_write(cec, cec->addresses & 255, HDMI_CEC_ADDR_L); in dw_hdmi_cec_log_addr()
106 dw_hdmi_write(cec, cec->addresses >> 8, HDMI_CEC_ADDR_H); in dw_hdmi_cec_log_addr()
114 struct dw_hdmi_cec *cec = cec_get_drvdata(adap); in dw_hdmi_cec_transmit() local
131 dw_hdmi_write(cec, msg->msg[i], HDMI_CEC_TX_DATA0 + i); in dw_hdmi_cec_transmit()
133 dw_hdmi_write(cec, msg->len, HDMI_CEC_TX_CNT); in dw_hdmi_cec_transmit()
134 dw_hdmi_mod(cec, HDMI_CEC_CTRL, CEC_TRANS_MASK, ctrl | CEC_CTRL_START); in dw_hdmi_cec_transmit()
142 struct dw_hdmi_cec *cec = cec_get_drvdata(adap); in dw_hdmi_cec_hardirq() local
143 unsigned int stat = dw_hdmi_read(cec, HDMI_IH_CEC_STAT0); in dw_hdmi_cec_hardirq()
149 dw_hdmi_write(cec, stat, HDMI_IH_CEC_STAT0); in dw_hdmi_cec_hardirq()
152 cec->tx_status = CEC_TX_STATUS_ERROR; in dw_hdmi_cec_hardirq()
153 cec->tx_done = true; in dw_hdmi_cec_hardirq()
156 cec->tx_status = CEC_TX_STATUS_OK; in dw_hdmi_cec_hardirq()
157 cec->tx_done = true; in dw_hdmi_cec_hardirq()
160 cec->tx_status = CEC_TX_STATUS_NACK; in dw_hdmi_cec_hardirq()
161 cec->tx_done = true; in dw_hdmi_cec_hardirq()
168 len = dw_hdmi_read(cec, HDMI_CEC_RX_CNT); in dw_hdmi_cec_hardirq()
169 if (len > sizeof(cec->rx_msg.msg)) in dw_hdmi_cec_hardirq()
170 len = sizeof(cec->rx_msg.msg); in dw_hdmi_cec_hardirq()
173 cec->rx_msg.msg[i] = in dw_hdmi_cec_hardirq()
174 dw_hdmi_read(cec, HDMI_CEC_RX_DATA0 + i); in dw_hdmi_cec_hardirq()
176 dw_hdmi_write(cec, 0, HDMI_CEC_LOCK); in dw_hdmi_cec_hardirq()
178 cec->rx_msg.len = len; in dw_hdmi_cec_hardirq()
180 cec->rx_done = true; in dw_hdmi_cec_hardirq()
191 struct dw_hdmi_cec *cec = cec_get_drvdata(adap); in dw_hdmi_cec_thread() local
193 if (cec->tx_done) { in dw_hdmi_cec_thread()
194 cec->tx_done = false; in dw_hdmi_cec_thread()
195 cec_transmit_attempt_done(adap, cec->tx_status); in dw_hdmi_cec_thread()
197 if (cec->rx_done) { in dw_hdmi_cec_thread()
198 cec->rx_done = false; in dw_hdmi_cec_thread()
200 cec_received_msg(adap, &cec->rx_msg); in dw_hdmi_cec_thread()
207 struct dw_hdmi_cec *cec = cec_get_drvdata(adap); in dw_hdmi_cec_enable() local
210 dw_hdmi_write(cec, 0, HDMI_CEC_POLARITY); in dw_hdmi_cec_enable()
212 if (cec->wake_en && cec->standby_en) { in dw_hdmi_cec_enable()
213 dw_hdmi_write(cec, 0xff, HDMI_IH_CEC_STAT0); in dw_hdmi_cec_enable()
214 dw_hdmi_mod(cec, HDMI_CEC_CTRL, CEC_CTRL_STANDBY, CEC_CTRL_STANDBY); in dw_hdmi_cec_enable()
215 dw_hdmi_write(cec, 0, HDMI_CEC_LOCK); in dw_hdmi_cec_enable()
216 dw_hdmi_write(cec, 0xff, HDMI_CEC_WKUPCTRL); in dw_hdmi_cec_enable()
217 dw_hdmi_write(cec, ~(1 << 6), HDMI_CEC_MASK); in dw_hdmi_cec_enable()
218 dw_hdmi_write(cec, ~(1 << 6), HDMI_IH_MUTE_CEC_STAT0); in dw_hdmi_cec_enable()
219 dw_hdmi_write(cec, 0x01, HDMI_IH_MUTE); in dw_hdmi_cec_enable()
221 cec->ops->disable(cec->hdmi); in dw_hdmi_cec_enable()
226 dw_hdmi_cec_log_addr(cec->adap, CEC_LOG_ADDR_INVALID); in dw_hdmi_cec_enable()
227 dw_hdmi_mod(cec, HDMI_CEC_CTRL, CEC_CTRL_STANDBY, 0); in dw_hdmi_cec_enable()
228 dw_hdmi_write(cec, 0x02, HDMI_IH_MUTE); in dw_hdmi_cec_enable()
229 dw_hdmi_write(cec, ~0, HDMI_IH_CEC_STAT0); in dw_hdmi_cec_enable()
230 dw_hdmi_write(cec, 0, HDMI_CEC_LOCK); in dw_hdmi_cec_enable()
232 cec->ops->enable(cec->hdmi); in dw_hdmi_cec_enable()
236 dw_hdmi_write(cec, irqs, HDMI_CEC_POLARITY); in dw_hdmi_cec_enable()
237 dw_hdmi_write(cec, ~irqs, HDMI_CEC_MASK); in dw_hdmi_cec_enable()
238 dw_hdmi_write(cec, ~irqs, HDMI_IH_MUTE_CEC_STAT0); in dw_hdmi_cec_enable()
251 struct dw_hdmi_cec *cec = data; in dw_hdmi_cec_del() local
253 cec_delete_adapter(cec->adap); in dw_hdmi_cec_del()
259 struct dw_hdmi_cec *cec = cec_get_drvdata(adap); in dw_hdmi_cec_wake_irq() local
262 cec_int = dw_hdmi_read(cec, HDMI_IH_CEC_STAT0); in dw_hdmi_cec_wake_irq()
266 dw_hdmi_write(cec, 0x02, HDMI_IH_MUTE); in dw_hdmi_cec_wake_irq()
267 dw_hdmi_write(cec, cec_int, HDMI_IH_CEC_STAT0); in dw_hdmi_cec_wake_irq()
268 dw_hdmi_write(cec, 0x00, HDMI_CEC_WKUPCTRL); in dw_hdmi_cec_wake_irq()
270 if (!cec->wake_en) in dw_hdmi_cec_wake_irq()
279 struct dw_hdmi_cec *cec = cec_get_drvdata(adap); in dw_hdmi_cec_wake_thread() local
281 mutex_lock(&cec->wake_lock); in dw_hdmi_cec_wake_thread()
283 if (!cec->standby_en) { in dw_hdmi_cec_wake_thread()
284 mutex_unlock(&cec->wake_lock); in dw_hdmi_cec_wake_thread()
287 cec->standby_en = false; in dw_hdmi_cec_wake_thread()
289 dev_dbg(cec->dev, "wakeup opcode:0x%x\n", dw_hdmi_read(cec, HDMI_CEC_RX_DATA1)); in dw_hdmi_cec_wake_thread()
290 input_event(cec->devinput, EV_KEY, KEY_POWER, 1); in dw_hdmi_cec_wake_thread()
291 input_sync(cec->devinput); in dw_hdmi_cec_wake_thread()
292 input_event(cec->devinput, EV_KEY, KEY_POWER, 0); in dw_hdmi_cec_wake_thread()
293 input_sync(cec->devinput); in dw_hdmi_cec_wake_thread()
294 mutex_unlock(&cec->wake_lock); in dw_hdmi_cec_wake_thread()
299 static int rockchip_hdmi_cec_input_init(struct dw_hdmi_cec *cec) in rockchip_hdmi_cec_input_init() argument
303 cec->devinput = devm_input_allocate_device(cec->dev); in rockchip_hdmi_cec_input_init()
304 if (!cec->devinput) in rockchip_hdmi_cec_input_init()
307 cec->devinput->name = "hdmi_cec_key"; in rockchip_hdmi_cec_input_init()
308 cec->devinput->phys = "hdmi_cec_key/input0"; in rockchip_hdmi_cec_input_init()
309 cec->devinput->id.bustype = BUS_HOST; in rockchip_hdmi_cec_input_init()
310 cec->devinput->id.vendor = 0x0001; in rockchip_hdmi_cec_input_init()
311 cec->devinput->id.product = 0x0001; in rockchip_hdmi_cec_input_init()
312 cec->devinput->id.version = 0x0100; in rockchip_hdmi_cec_input_init()
314 err = input_register_device(cec->devinput); in rockchip_hdmi_cec_input_init()
316 input_free_device(cec->devinput); in rockchip_hdmi_cec_input_init()
319 input_set_capability(cec->devinput, EV_KEY, KEY_POWER); in rockchip_hdmi_cec_input_init()
328 struct dw_hdmi_cec *cec = cec_get_drvdata(adap); in cec_standby() local
330 mutex_lock(&cec->wake_lock); in cec_standby()
332 mutex_unlock(&cec->wake_lock); in cec_standby()
336 cec->standby_en = !en; in cec_standby()
338 mutex_unlock(&cec->wake_lock); in cec_standby()
343 static long cec_func_en(struct dw_hdmi_cec *cec, int __user *parg) in cec_func_en() argument
350 cec->wake_en = (en_mask & CEC_EN) && (en_mask & CEC_WAKE); in cec_func_en()
357 struct dw_hdmi_cec *cec; in dw_hdmi_cec_ioctl() local
365 cec = container_of(misc_dev, struct dw_hdmi_cec, misc_dev); in dw_hdmi_cec_ioctl()
370 return cec_standby(cec->adap, data); in dw_hdmi_cec_ioctl()
372 return cec_func_en(cec, data); in dw_hdmi_cec_ioctl()
400 struct dw_hdmi_cec *cec = platform_get_drvdata(pdev); in dw_hdmi_cec_hpd_wake_up() local
402 mutex_lock(&cec->wake_lock); in dw_hdmi_cec_hpd_wake_up()
404 if (!cec->standby_en) { in dw_hdmi_cec_hpd_wake_up()
405 mutex_unlock(&cec->wake_lock); in dw_hdmi_cec_hpd_wake_up()
408 cec->standby_en = false; in dw_hdmi_cec_hpd_wake_up()
410 dw_hdmi_write(cec, 0x02, HDMI_IH_MUTE); in dw_hdmi_cec_hpd_wake_up()
412 input_event(cec->devinput, EV_KEY, KEY_POWER, 1); in dw_hdmi_cec_hpd_wake_up()
413 input_sync(cec->devinput); in dw_hdmi_cec_hpd_wake_up()
414 input_event(cec->devinput, EV_KEY, KEY_POWER, 0); in dw_hdmi_cec_hpd_wake_up()
415 input_sync(cec->devinput); in dw_hdmi_cec_hpd_wake_up()
416 mutex_unlock(&cec->wake_lock); in dw_hdmi_cec_hpd_wake_up()
426 struct dw_hdmi_cec *cec; in dw_hdmi_cec_probe() local
435 * between the HDMI hardware and its associated CEC chardev. in dw_hdmi_cec_probe()
437 cec = devm_kzalloc(&pdev->dev, sizeof(*cec), GFP_KERNEL); in dw_hdmi_cec_probe()
438 if (!cec) in dw_hdmi_cec_probe()
441 cec->dev = &pdev->dev; in dw_hdmi_cec_probe()
442 cec->irq = data->irq; in dw_hdmi_cec_probe()
443 cec->wake_irq = data->wake_irq; in dw_hdmi_cec_probe()
444 cec->ops = data->ops; in dw_hdmi_cec_probe()
445 cec->hdmi = data->hdmi; in dw_hdmi_cec_probe()
447 mutex_init(&cec->wake_lock); in dw_hdmi_cec_probe()
449 platform_set_drvdata(pdev, cec); in dw_hdmi_cec_probe()
451 dw_hdmi_write(cec, 0, HDMI_CEC_TX_CNT); in dw_hdmi_cec_probe()
452 dw_hdmi_write(cec, ~0, HDMI_CEC_MASK); in dw_hdmi_cec_probe()
453 dw_hdmi_write(cec, ~0, HDMI_IH_MUTE_CEC_STAT0); in dw_hdmi_cec_probe()
454 dw_hdmi_write(cec, 0, HDMI_CEC_POLARITY); in dw_hdmi_cec_probe()
456 cec->adap = cec_allocate_adapter(&dw_hdmi_cec_ops, cec, "dw_hdmi", in dw_hdmi_cec_probe()
460 if (IS_ERR(cec->adap)) in dw_hdmi_cec_probe()
461 return PTR_ERR(cec->adap); in dw_hdmi_cec_probe()
463 dw_hdmi_set_cec_adap(cec->hdmi, cec->adap); in dw_hdmi_cec_probe()
466 cec->adap->owner = THIS_MODULE; in dw_hdmi_cec_probe()
468 ret = devm_add_action(&pdev->dev, dw_hdmi_cec_del, cec); in dw_hdmi_cec_probe()
470 cec_delete_adapter(cec->adap); in dw_hdmi_cec_probe()
474 ret = devm_request_threaded_irq(&pdev->dev, cec->irq, in dw_hdmi_cec_probe()
477 "dw-hdmi-cec", cec->adap); in dw_hdmi_cec_probe()
481 if (cec->wake_irq > 0) { in dw_hdmi_cec_probe()
482 ret = devm_request_threaded_irq(&pdev->dev, cec->wake_irq, in dw_hdmi_cec_probe()
486 "cec-wakeup", cec->adap); in dw_hdmi_cec_probe()
494 enable_irq_wake(cec->wake_irq); in dw_hdmi_cec_probe()
497 cec->notify = cec_notifier_cec_adap_register(pdev->dev.parent, in dw_hdmi_cec_probe()
498 NULL, cec->adap); in dw_hdmi_cec_probe()
499 if (!cec->notify) in dw_hdmi_cec_probe()
502 ret = cec_register_adapter(cec->adap, pdev->dev.parent); in dw_hdmi_cec_probe()
504 cec_notifier_cec_adap_unregister(cec->notify, cec->adap); in dw_hdmi_cec_probe()
509 * CEC documentation says we must not call cec_delete_adapter in dw_hdmi_cec_probe()
512 devm_remove_action(&pdev->dev, dw_hdmi_cec_del, cec); in dw_hdmi_cec_probe()
514 rockchip_hdmi_cec_input_init(cec); in dw_hdmi_cec_probe()
516 cec->misc_dev.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, "rk_cec"); in dw_hdmi_cec_probe()
517 if (!cec->misc_dev.name) in dw_hdmi_cec_probe()
519 cec->misc_dev.minor = MISC_DYNAMIC_MINOR; in dw_hdmi_cec_probe()
520 cec->misc_dev.fops = &dw_hdmi_cec_file_operations; in dw_hdmi_cec_probe()
521 cec->misc_dev.mode = 0666; in dw_hdmi_cec_probe()
523 ret = misc_register(&cec->misc_dev); in dw_hdmi_cec_probe()
525 dw_hdmi_cec_wake_ops_register(cec->hdmi, &cec_ops); in dw_hdmi_cec_probe()
532 struct dw_hdmi_cec *cec = platform_get_drvdata(pdev); in dw_hdmi_cec_remove() local
534 cec_notifier_cec_adap_unregister(cec->notify, cec->adap); in dw_hdmi_cec_remove()
535 cec_unregister_adapter(cec->adap); in dw_hdmi_cec_remove()
536 misc_deregister(&cec->misc_dev); in dw_hdmi_cec_remove()
545 .name = "dw-hdmi-cec",
551 MODULE_DESCRIPTION("Synopsys Designware HDMI CEC driver for i.MX");
553 MODULE_ALIAS(PLATFORM_MODULE_PREFIX "dw-hdmi-cec");