cregit-Linux how code gets into the kernel

Release 4.11 drivers/staging/media/s5p-cec/s5p_cec.c

/* drivers/media/platform/s5p-cec/s5p_cec.c
 *
 * Samsung S5P CEC driver
 *
 * Copyright (c) 2014 Samsung Electronics Co., Ltd.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This driver is based on the "cec interface driver for exynos soc" by
 * SangPil Moon.
 */

#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
#include <linux/mfd/syscon.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/timer.h>
#include <linux/workqueue.h>
#include <media/cec.h>

#include "exynos_hdmi_cec.h"
#include "regs-cec.h"
#include "s5p_cec.h"


#define CEC_NAME	"s5p-cec"


static int debug;
module_param(debug, int, 0644);
MODULE_PARM_DESC(debug, "debug level (0-2)");


static int s5p_cec_adap_enable(struct cec_adapter *adap, bool enable) { struct s5p_cec_dev *cec = adap->priv; if (enable) { pm_runtime_get_sync(cec->dev); s5p_cec_reset(cec); s5p_cec_set_divider(cec); s5p_cec_threshold(cec); s5p_cec_unmask_tx_interrupts(cec); s5p_cec_unmask_rx_interrupts(cec); s5p_cec_enable_rx(cec); } else { s5p_cec_mask_tx_interrupts(cec); s5p_cec_mask_rx_interrupts(cec); pm_runtime_disable(cec->dev); } return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski89100.00%1100.00%
Total89100.00%1100.00%


static int s5p_cec_adap_log_addr(struct cec_adapter *adap, u8 addr) { struct s5p_cec_dev *cec = adap->priv; s5p_cec_set_addr(cec, addr); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski33100.00%1100.00%
Total33100.00%1100.00%


static int s5p_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, u32 signal_free_time, struct cec_msg *msg) { struct s5p_cec_dev *cec = adap->priv; /* * Unclear if 0 retries are allowed by the hardware, so have 1 as * the minimum. */ s5p_cec_copy_packet(cec, msg->msg, msg->len, max(1, attempts - 1)); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski57100.00%1100.00%
Total57100.00%1100.00%


static irqreturn_t s5p_cec_irq_handler(int irq, void *priv) { struct s5p_cec_dev *cec = priv; u32 status = 0; status = s5p_cec_get_status(cec); dev_dbg(cec->dev, "irq received\n"); if (status & CEC_STATUS_TX_DONE) { if (status & CEC_STATUS_TX_ERROR) { dev_dbg(cec->dev, "CEC_STATUS_TX_ERROR set\n"); cec->tx = STATE_ERROR; } else { dev_dbg(cec->dev, "CEC_STATUS_TX_DONE\n"); cec->tx = STATE_DONE; } s5p_clr_pending_tx(cec); } if (status & CEC_STATUS_RX_DONE) { if (status & CEC_STATUS_RX_ERROR) { dev_dbg(cec->dev, "CEC_STATUS_RX_ERROR set\n"); s5p_cec_rx_reset(cec); s5p_cec_enable_rx(cec); } else { dev_dbg(cec->dev, "CEC_STATUS_RX_DONE set\n"); if (cec->rx != STATE_IDLE) dev_dbg(cec->dev, "Buffer overrun (worker did not process previous message)\n"); cec->rx = STATE_BUSY; cec->msg.len = status >> 24; cec->msg.rx_status = CEC_RX_STATUS_OK; s5p_cec_get_rx_buf(cec, cec->msg.len, cec->msg.msg); cec->rx = STATE_DONE; s5p_cec_enable_rx(cec); } /* Clear interrupt pending bit */ s5p_clr_pending_rx(cec); } return IRQ_WAKE_THREAD; }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski220100.00%1100.00%
Total220100.00%1100.00%


static irqreturn_t s5p_cec_irq_handler_thread(int irq, void *priv) { struct s5p_cec_dev *cec = priv; dev_dbg(cec->dev, "irq processing thread\n"); switch (cec->tx) { case STATE_DONE: cec_transmit_done(cec->adap, CEC_TX_STATUS_OK, 0, 0, 0, 0); cec->tx = STATE_IDLE; break; case STATE_ERROR: cec_transmit_done(cec->adap, CEC_TX_STATUS_MAX_RETRIES | CEC_TX_STATUS_ERROR, 0, 0, 0, 1); cec->tx = STATE_IDLE; break; case STATE_BUSY: dev_err(cec->dev, "state set to busy, this should not occur here\n"); break; default: break; } switch (cec->rx) { case STATE_DONE: cec_received_msg(cec->adap, &cec->msg); cec->rx = STATE_IDLE; break; default: break; } return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski143100.00%1100.00%
Total143100.00%1100.00%

static const struct cec_adap_ops s5p_cec_adap_ops = { .adap_enable = s5p_cec_adap_enable, .adap_log_addr = s5p_cec_adap_log_addr, .adap_transmit = s5p_cec_adap_transmit, };
static int s5p_cec_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; struct s5p_cec_dev *cec; int ret; cec = devm_kzalloc(&pdev->dev, sizeof(*cec), GFP_KERNEL); if (!cec) return -ENOMEM; cec->dev = dev; cec->irq = platform_get_irq(pdev, 0); if (cec->irq < 0) return cec->irq; ret = devm_request_threaded_irq(dev, cec->irq, s5p_cec_irq_handler, s5p_cec_irq_handler_thread, 0, pdev->name, cec); if (ret) return ret; cec->clk = devm_clk_get(dev, "hdmicec"); if (IS_ERR(cec->clk)) return PTR_ERR(cec->clk); cec->pmu = syscon_regmap_lookup_by_phandle(dev->of_node, "samsung,syscon-phandle"); if (IS_ERR(cec->pmu)) return -EPROBE_DEFER; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); cec->reg = devm_ioremap_resource(dev, res); if (IS_ERR(cec->reg)) return PTR_ERR(cec->reg); cec->adap = cec_allocate_adapter(&s5p_cec_adap_ops, cec, CEC_NAME, CEC_CAP_PHYS_ADDR | CEC_CAP_LOG_ADDRS | CEC_CAP_TRANSMIT | CEC_CAP_PASSTHROUGH | CEC_CAP_RC, 1); ret = PTR_ERR_OR_ZERO(cec->adap); if (ret) return ret; ret = cec_register_adapter(cec->adap, &pdev->dev); if (ret) { cec_delete_adapter(cec->adap); return ret; } platform_set_drvdata(pdev, cec); pm_runtime_enable(dev); dev_dbg(dev, "successfuly probed\n"); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski30298.05%133.33%
Hans Verkuil51.62%133.33%
Christophe Jaillet10.32%133.33%
Total308100.00%3100.00%


static int s5p_cec_remove(struct platform_device *pdev) { struct s5p_cec_dev *cec = platform_get_drvdata(pdev); cec_unregister_adapter(cec->adap); pm_runtime_disable(&pdev->dev); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski39100.00%1100.00%
Total39100.00%1100.00%


static int __maybe_unused s5p_cec_runtime_suspend(struct device *dev) { struct s5p_cec_dev *cec = dev_get_drvdata(dev); clk_disable_unprepare(cec->clk); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski3196.88%150.00%
Arnd Bergmann13.12%150.00%
Total32100.00%2100.00%


static int __maybe_unused s5p_cec_runtime_resume(struct device *dev) { struct s5p_cec_dev *cec = dev_get_drvdata(dev); int ret; ret = clk_prepare_enable(cec->clk); if (ret < 0) return ret; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski4597.83%150.00%
Arnd Bergmann12.17%150.00%
Total46100.00%2100.00%

static const struct dev_pm_ops s5p_cec_pm_ops = { SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume) SET_RUNTIME_PM_OPS(s5p_cec_runtime_suspend, s5p_cec_runtime_resume, NULL) }; static const struct of_device_id s5p_cec_match[] = { { .compatible = "samsung,s5p-cec", }, {}, }; MODULE_DEVICE_TABLE(of, s5p_cec_match); static struct platform_driver s5p_cec_pdrv = { .probe = s5p_cec_probe, .remove = s5p_cec_remove, .driver = { .name = CEC_NAME, .of_match_table = s5p_cec_match, .pm = &s5p_cec_pm_ops, }, }; module_platform_driver(s5p_cec_pdrv); MODULE_AUTHOR("Kamil Debski <kamil@wypas.org>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Samsung S5P CEC driver");

Overall Contributors

PersonTokensPropCommitsCommitProp
Kamil Debski114698.54%116.67%
Javier Martinez Canillas70.60%116.67%
Hans Verkuil50.43%116.67%
Arnd Bergmann20.17%116.67%
Marek Szyprowski20.17%116.67%
Christophe Jaillet10.09%116.67%
Total1163100.00%6100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.