Lines Matching +full:cec +full:- +full:irq
1 // SPDX-License-Identifier: GPL-2.0
3 * Driver for the Chrontel CH7322 CEC Controller
11 * - This device powers on in Auto Mode which has limited functionality. This
16 #include <linux/cec.h>
24 #include <media/cec.h>
25 #include <media/cec-notifier.h>
32 /* Write buffer is 0x01-0x10 */
41 /* Read buffer is 0x41-0x50 */
153 struct cec_adapter *cec; member
168 unsigned int len = msg->len; in ch7322_send_message()
172 WARN_ON(!mutex_is_locked(&ch7322->mutex)); in ch7322_send_message()
175 return -EINVAL; in ch7322_send_message()
177 ret = regmap_read(ch7322->regmap, CH7322_WRITE, &val); in ch7322_send_message()
183 return -EBUSY; in ch7322_send_message()
185 if (cec_msg_opcode(msg) == -1 && in ch7322_send_message()
187 ch7322->tx_flags = CH7322_TX_FLAG_NACK | CH7322_TX_FLAG_RETRY; in ch7322_send_message()
189 ch7322->tx_flags = CH7322_TX_FLAG_NACK; in ch7322_send_message()
191 ch7322->tx_flags = CH7322_TX_FLAG_RETRY; in ch7322_send_message()
194 ret = regmap_write(ch7322->regmap, CH7322_WRITE, len - 1); in ch7322_send_message()
199 ret = regmap_write(ch7322->regmap, in ch7322_send_message()
200 CH7322_WRBUF + i, msg->msg[i]); in ch7322_send_message()
214 WARN_ON(!mutex_is_locked(&ch7322->mutex)); in ch7322_receive_message()
216 ret = regmap_read(ch7322->regmap, CH7322_READ, &val); in ch7322_receive_message()
222 return -EIO; in ch7322_receive_message()
224 msg->len = (val & CH7322_READ_NMASK) + 1; in ch7322_receive_message()
228 ret = regmap_read(ch7322->regmap, CH7322_RDBUF + i, &val); in ch7322_receive_message()
231 msg->msg[i] = (u8)val; in ch7322_receive_message()
243 mutex_lock(&ch7322->mutex); in ch7322_tx_done()
244 ret = regmap_read(ch7322->regmap, CH7322_WRITE, &val); in ch7322_tx_done()
245 flags = ch7322->tx_flags; in ch7322_tx_done()
246 mutex_unlock(&ch7322->mutex); in ch7322_tx_done()
249 * The device returns a one-bit OK status which usually means ACK but in ch7322_tx_done()
267 cec_transmit_attempt_done(ch7322->cec, status); in ch7322_tx_done()
275 mutex_lock(&ch7322->mutex); in ch7322_rx_done()
277 mutex_unlock(&ch7322->mutex); in ch7322_rx_done()
280 dev_err(&ch7322->i2c->dev, "cec receive error: %d\n", ret); in ch7322_rx_done()
282 cec_received_msg(ch7322->cec, &msg); in ch7322_rx_done()
295 mutex_lock(&ch7322->mutex); in ch7322_phys_addr()
296 ret |= regmap_read(ch7322->regmap, CH7322_PARH, &pah); in ch7322_phys_addr()
297 ret |= regmap_read(ch7322->regmap, CH7322_PARL, &pal); in ch7322_phys_addr()
298 mutex_unlock(&ch7322->mutex); in ch7322_phys_addr()
301 dev_err(&ch7322->i2c->dev, "phys addr error\n"); in ch7322_phys_addr()
303 cec_s_phys_addr(ch7322->cec, pal | (pah << 8), false); in ch7322_phys_addr()
306 static irqreturn_t ch7322_irq(int irq, void *dev) in ch7322_irq() argument
311 mutex_lock(&ch7322->mutex); in ch7322_irq()
312 regmap_read(ch7322->regmap, CH7322_INTDATA, &data); in ch7322_irq()
313 regmap_write(ch7322->regmap, CH7322_INTDATA, data); in ch7322_irq()
314 mutex_unlock(&ch7322->mutex); in ch7322_irq()
317 cec_phys_addr_invalidate(ch7322->cec); in ch7322_irq()
329 dev_dbg(&ch7322->i2c->dev, "unknown error\n"); in ch7322_irq()
345 mutex_lock(&ch7322->mutex); in ch7322_cec_adap_log_addr()
346 ret = regmap_update_bits(ch7322->regmap, CH7322_ADDLW, in ch7322_cec_adap_log_addr()
348 mutex_unlock(&ch7322->mutex); in ch7322_cec_adap_log_addr()
359 mutex_lock(&ch7322->mutex); in ch7322_cec_adap_transmit()
361 mutex_unlock(&ch7322->mutex); in ch7322_cec_adap_transmit()
381 { "i2c-PRP0001:00", "0000:00:02.0", "Port B" },
382 { "i2c-PRP0001:01", "0000:00:02.0", "Port C" },
397 /* Make a best-effort attempt to locate a matching HDMI port */
412 for (conn = system->driver_data; conn->dev_name; conn++) { in ch7322_get_port()
413 if (!strcmp(dev_name(&client->dev), conn->dev_name)) { in ch7322_get_port()
417 conn->pci_name); in ch7322_get_port()
419 return -EPROBE_DEFER; in ch7322_get_port()
424 *port = conn->port_name; in ch7322_get_port()
464 ch7322 = devm_kzalloc(&client->dev, sizeof(*ch7322), GFP_KERNEL); in ch7322_probe()
466 return -ENOMEM; in ch7322_probe()
468 ch7322->regmap = devm_regmap_init_i2c(client, &ch7322_regmap); in ch7322_probe()
469 if (IS_ERR(ch7322->regmap)) in ch7322_probe()
470 return PTR_ERR(ch7322->regmap); in ch7322_probe()
472 ret = regmap_read(ch7322->regmap, CH7322_DID, &val); in ch7322_probe()
477 return -EOPNOTSUPP; in ch7322_probe()
479 mutex_init(&ch7322->mutex); in ch7322_probe()
480 ch7322->i2c = client; in ch7322_probe()
481 ch7322->tx_flags = 0; in ch7322_probe()
486 ret = regmap_write(ch7322->regmap, CH7322_MODE, CH7322_MODE_SW); in ch7322_probe()
491 ret = regmap_update_bits(ch7322->regmap, CH7322_CTL, in ch7322_probe()
496 ch7322->cec = cec_allocate_adapter(&ch7322_cec_adap_ops, ch7322, in ch7322_probe()
497 dev_name(&client->dev), in ch7322_probe()
500 if (IS_ERR(ch7322->cec)) { in ch7322_probe()
501 ret = PTR_ERR(ch7322->cec); in ch7322_probe()
505 ch7322->cec->adap_controls_phys_addr = true; in ch7322_probe()
510 ch7322->cec); in ch7322_probe()
512 ret = -ENOMEM; in ch7322_probe()
518 ret = regmap_write(ch7322->regmap, CH7322_CFG1, 0); in ch7322_probe()
521 ret = regmap_write(ch7322->regmap, CH7322_INTCTL, CH7322_INTCTL_INTPB); in ch7322_probe()
524 ret = regmap_write(ch7322->regmap, CH7322_INTDATA, 0xff); in ch7322_probe()
529 ret = regmap_read(ch7322->regmap, CH7322_ADDLR, &val); in ch7322_probe()
535 ret = devm_request_threaded_irq(&client->dev, client->irq, NULL, in ch7322_probe()
538 client->name, ch7322); in ch7322_probe()
543 mutex_lock(&ch7322->mutex); in ch7322_probe()
544 ret = regmap_write(ch7322->regmap, CH7322_INTCTL, 0xff); in ch7322_probe()
545 mutex_unlock(&ch7322->mutex); in ch7322_probe()
550 ret = cec_register_adapter(ch7322->cec, &client->dev); in ch7322_probe()
554 dev_info(&client->dev, "device registered\n"); in ch7322_probe()
560 cec_notifier_cec_adap_unregister(notifier, ch7322->cec); in ch7322_probe()
562 cec_delete_adapter(ch7322->cec); in ch7322_probe()
564 mutex_destroy(&ch7322->mutex); in ch7322_probe()
573 mutex_lock(&ch7322->mutex); in ch7322_remove()
574 regmap_write(ch7322->regmap, CH7322_INTCTL, CH7322_INTCTL_INTPB); in ch7322_remove()
575 mutex_unlock(&ch7322->mutex); in ch7322_remove()
577 cec_unregister_adapter(ch7322->cec); in ch7322_remove()
578 mutex_destroy(&ch7322->mutex); in ch7322_remove()
580 dev_info(&client->dev, "device unregistered\n"); in ch7322_remove()
600 MODULE_DESCRIPTION("Chrontel CH7322 CEC Controller Driver");