Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * meson-ir-tx.c - Amlogic Meson IR TX driver
0004  *
0005  * Copyright (c) 2021, SberDevices. All Rights Reserved.
0006  *
0007  * Author: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
0008  */
0009 
0010 #include <linux/device.h>
0011 #include <linux/module.h>
0012 #include <linux/sched.h>
0013 #include <linux/platform_device.h>
0014 #include <linux/of.h>
0015 #include <linux/interrupt.h>
0016 #include <linux/spinlock.h>
0017 #include <linux/of_irq.h>
0018 #include <linux/clk.h>
0019 #include <linux/slab.h>
0020 #include <media/rc-core.h>
0021 
0022 #define DEVICE_NAME "Meson IR TX"
0023 #define DRIVER_NAME "meson-ir-tx"
0024 
0025 #define MIRTX_DEFAULT_CARRIER       38000
0026 #define MIRTX_DEFAULT_DUTY_CYCLE    50
0027 #define MIRTX_FIFO_THD          32
0028 
0029 #define IRB_MOD_1US_CLK_RATE    1000000
0030 
0031 #define IRB_FIFO_LEN    128
0032 
0033 #define IRB_ADDR0   0x0
0034 #define IRB_ADDR1   0x4
0035 #define IRB_ADDR2   0x8
0036 #define IRB_ADDR3   0xc
0037 
0038 #define IRB_MAX_DELAY   (1 << 10)
0039 #define IRB_DELAY_MASK  (IRB_MAX_DELAY - 1)
0040 
0041 /* IRCTRL_IR_BLASTER_ADDR0 */
0042 #define IRB_MOD_CLK(x)      ((x) << 12)
0043 #define IRB_MOD_SYS_CLK     0
0044 #define IRB_MOD_XTAL3_CLK   1
0045 #define IRB_MOD_1US_CLK     2
0046 #define IRB_MOD_10US_CLK    3
0047 #define IRB_INIT_HIGH       BIT(2)
0048 #define IRB_ENABLE      BIT(0)
0049 
0050 /* IRCTRL_IR_BLASTER_ADDR2 */
0051 #define IRB_MOD_COUNT(lo, hi)   ((((lo) - 1) << 16) | ((hi) - 1))
0052 
0053 /* IRCTRL_IR_BLASTER_ADDR2 */
0054 #define IRB_WRITE_FIFO  BIT(16)
0055 #define IRB_MOD_ENABLE  BIT(12)
0056 #define IRB_TB_1US  (0x0 << 10)
0057 #define IRB_TB_10US (0x1 << 10)
0058 #define IRB_TB_100US    (0x2 << 10)
0059 #define IRB_TB_MOD_CLK  (0x3 << 10)
0060 
0061 /* IRCTRL_IR_BLASTER_ADDR3 */
0062 #define IRB_FIFO_THD_PENDING    BIT(16)
0063 #define IRB_FIFO_IRQ_ENABLE BIT(8)
0064 
0065 struct meson_irtx {
0066     struct device *dev;
0067     void __iomem *reg_base;
0068     u32 *buf;
0069     unsigned int buf_len;
0070     unsigned int buf_head;
0071     unsigned int carrier;
0072     unsigned int duty_cycle;
0073     /* Locks buf */
0074     spinlock_t lock;
0075     struct completion completion;
0076     unsigned long clk_rate;
0077 };
0078 
0079 static void meson_irtx_set_mod(struct meson_irtx *ir)
0080 {
0081     unsigned int cnt = DIV_ROUND_CLOSEST(ir->clk_rate, ir->carrier);
0082     unsigned int pulse_cnt = DIV_ROUND_CLOSEST(cnt * ir->duty_cycle, 100);
0083     unsigned int space_cnt = cnt - pulse_cnt;
0084 
0085     dev_dbg(ir->dev, "F_mod = %uHz, T_mod = %luns, duty_cycle = %u%%\n",
0086         ir->carrier, NSEC_PER_SEC / ir->clk_rate * cnt,
0087         100 * pulse_cnt / cnt);
0088 
0089     writel(IRB_MOD_COUNT(pulse_cnt, space_cnt),
0090            ir->reg_base + IRB_ADDR1);
0091 }
0092 
0093 static void meson_irtx_setup(struct meson_irtx *ir, unsigned int clk_nr)
0094 {
0095     /*
0096      * Disable the TX, set modulator clock tick and set initialize
0097      * output to be high. Set up carrier frequency and duty cycle. Then
0098      * unset initialize output. Enable FIFO interrupt, set FIFO interrupt
0099      * threshold. Finally, enable the transmitter back.
0100      */
0101     writel(~IRB_ENABLE & (IRB_MOD_CLK(clk_nr) | IRB_INIT_HIGH),
0102            ir->reg_base + IRB_ADDR0);
0103     meson_irtx_set_mod(ir);
0104     writel(readl(ir->reg_base + IRB_ADDR0) & ~IRB_INIT_HIGH,
0105            ir->reg_base + IRB_ADDR0);
0106     writel(IRB_FIFO_IRQ_ENABLE | MIRTX_FIFO_THD,
0107            ir->reg_base + IRB_ADDR3);
0108     writel(readl(ir->reg_base + IRB_ADDR0) | IRB_ENABLE,
0109            ir->reg_base + IRB_ADDR0);
0110 }
0111 
0112 static u32 meson_irtx_prepare_pulse(struct meson_irtx *ir, unsigned int time)
0113 {
0114     unsigned int delay;
0115     unsigned int tb = IRB_TB_MOD_CLK;
0116     unsigned int tb_us = DIV_ROUND_CLOSEST(USEC_PER_SEC, ir->carrier);
0117 
0118     delay = (DIV_ROUND_CLOSEST(time, tb_us) - 1) & IRB_DELAY_MASK;
0119 
0120     return ((IRB_WRITE_FIFO | IRB_MOD_ENABLE) | tb | delay);
0121 }
0122 
0123 static u32 meson_irtx_prepare_space(struct meson_irtx *ir, unsigned int time)
0124 {
0125     unsigned int delay;
0126     unsigned int tb = IRB_TB_100US;
0127     unsigned int tb_us = 100;
0128 
0129     if (time <= IRB_MAX_DELAY) {
0130         tb = IRB_TB_1US;
0131         tb_us = 1;
0132     } else if (time <= 10 * IRB_MAX_DELAY) {
0133         tb = IRB_TB_10US;
0134         tb_us = 10;
0135     } else if (time <= 100 * IRB_MAX_DELAY) {
0136         tb = IRB_TB_100US;
0137         tb_us = 100;
0138     }
0139 
0140     delay = (DIV_ROUND_CLOSEST(time, tb_us) - 1) & IRB_DELAY_MASK;
0141 
0142     return ((IRB_WRITE_FIFO & ~IRB_MOD_ENABLE) | tb | delay);
0143 }
0144 
0145 static void meson_irtx_send_buffer(struct meson_irtx *ir)
0146 {
0147     unsigned int nr = 0;
0148     unsigned int max_fifo_level = IRB_FIFO_LEN - MIRTX_FIFO_THD;
0149 
0150     while (ir->buf_head < ir->buf_len && nr < max_fifo_level) {
0151         writel(ir->buf[ir->buf_head], ir->reg_base + IRB_ADDR2);
0152 
0153         ir->buf_head++;
0154         nr++;
0155     }
0156 }
0157 
0158 static bool meson_irtx_check_buf(struct meson_irtx *ir,
0159                  unsigned int *buf, unsigned int len)
0160 {
0161     unsigned int i;
0162 
0163     for (i = 0; i < len; i++) {
0164         unsigned int max_tb_us;
0165         /*
0166          * Max space timebase is 100 us.
0167          * Pulse timebase equals to carrier period.
0168          */
0169         if (i % 2 == 0)
0170             max_tb_us = USEC_PER_SEC / ir->carrier;
0171         else
0172             max_tb_us = 100;
0173 
0174         if (buf[i] >= max_tb_us * IRB_MAX_DELAY)
0175             return false;
0176     }
0177 
0178     return true;
0179 }
0180 
0181 static void meson_irtx_fill_buf(struct meson_irtx *ir, u32 *dst_buf,
0182                 unsigned int *src_buf, unsigned int len)
0183 {
0184     unsigned int i;
0185 
0186     for (i = 0; i < len; i++) {
0187         if (i % 2 == 0)
0188             dst_buf[i] = meson_irtx_prepare_pulse(ir, src_buf[i]);
0189         else
0190             dst_buf[i] = meson_irtx_prepare_space(ir, src_buf[i]);
0191     }
0192 }
0193 
0194 static irqreturn_t meson_irtx_irqhandler(int irq, void *data)
0195 {
0196     unsigned long flags;
0197     struct meson_irtx *ir = data;
0198 
0199     writel(readl(ir->reg_base + IRB_ADDR3) & ~IRB_FIFO_THD_PENDING,
0200            ir->reg_base + IRB_ADDR3);
0201 
0202     if (completion_done(&ir->completion))
0203         return IRQ_HANDLED;
0204 
0205     spin_lock_irqsave(&ir->lock, flags);
0206     if (ir->buf_head < ir->buf_len)
0207         meson_irtx_send_buffer(ir);
0208     else
0209         complete(&ir->completion);
0210     spin_unlock_irqrestore(&ir->lock, flags);
0211 
0212     return IRQ_HANDLED;
0213 }
0214 
0215 static int meson_irtx_set_carrier(struct rc_dev *rc, u32 carrier)
0216 {
0217     struct meson_irtx *ir = rc->priv;
0218 
0219     if (carrier == 0)
0220         return -EINVAL;
0221 
0222     ir->carrier = carrier;
0223     meson_irtx_set_mod(ir);
0224 
0225     return 0;
0226 }
0227 
0228 static int meson_irtx_set_duty_cycle(struct rc_dev *rc, u32 duty_cycle)
0229 {
0230     struct meson_irtx *ir = rc->priv;
0231 
0232     ir->duty_cycle = duty_cycle;
0233     meson_irtx_set_mod(ir);
0234 
0235     return 0;
0236 }
0237 
0238 static void meson_irtx_update_buf(struct meson_irtx *ir, u32 *buf,
0239                   unsigned int len, unsigned int head)
0240 {
0241     ir->buf = buf;
0242     ir->buf_len = len;
0243     ir->buf_head = head;
0244 }
0245 
0246 static int meson_irtx_transmit(struct rc_dev *rc, unsigned int *buf,
0247                    unsigned int len)
0248 {
0249     unsigned long flags;
0250     struct meson_irtx *ir = rc->priv;
0251     u32 *tx_buf;
0252     int ret = len;
0253 
0254     if (!meson_irtx_check_buf(ir, buf, len))
0255         return -EINVAL;
0256 
0257     tx_buf = kmalloc_array(len, sizeof(u32), GFP_KERNEL);
0258     if (!tx_buf)
0259         return -ENOMEM;
0260 
0261     meson_irtx_fill_buf(ir, tx_buf, buf, len);
0262     dev_dbg(ir->dev, "TX buffer filled, length = %u\n", len);
0263 
0264     spin_lock_irqsave(&ir->lock, flags);
0265     meson_irtx_update_buf(ir, tx_buf, len, 0);
0266     reinit_completion(&ir->completion);
0267     meson_irtx_send_buffer(ir);
0268     spin_unlock_irqrestore(&ir->lock, flags);
0269 
0270     if (!wait_for_completion_timeout(&ir->completion,
0271                      usecs_to_jiffies(IR_MAX_DURATION)))
0272         ret = -ETIMEDOUT;
0273 
0274     spin_lock_irqsave(&ir->lock, flags);
0275     kfree(ir->buf);
0276     meson_irtx_update_buf(ir, NULL, 0, 0);
0277     spin_unlock_irqrestore(&ir->lock, flags);
0278 
0279     return ret;
0280 }
0281 
0282 static int meson_irtx_mod_clock_probe(struct meson_irtx *ir,
0283                       unsigned int *clk_nr)
0284 {
0285     struct device_node *np = ir->dev->of_node;
0286     struct clk *clock;
0287 
0288     if (!np)
0289         return -ENODEV;
0290 
0291     clock = devm_clk_get(ir->dev, "xtal");
0292     if (IS_ERR(clock) || clk_prepare_enable(clock))
0293         return -ENODEV;
0294 
0295     *clk_nr = IRB_MOD_XTAL3_CLK;
0296     ir->clk_rate = clk_get_rate(clock) / 3;
0297 
0298     if (ir->clk_rate < IRB_MOD_1US_CLK_RATE) {
0299         *clk_nr = IRB_MOD_1US_CLK;
0300         ir->clk_rate = IRB_MOD_1US_CLK_RATE;
0301     }
0302 
0303     dev_info(ir->dev, "F_clk = %luHz\n", ir->clk_rate);
0304 
0305     return 0;
0306 }
0307 
0308 static int __init meson_irtx_probe(struct platform_device *pdev)
0309 {
0310     struct device *dev = &pdev->dev;
0311     struct meson_irtx *ir;
0312     struct rc_dev *rc;
0313     int irq;
0314     unsigned int clk_nr;
0315     int ret;
0316 
0317     ir = devm_kzalloc(dev, sizeof(*ir), GFP_KERNEL);
0318     if (!ir)
0319         return -ENOMEM;
0320 
0321     ir->reg_base = devm_platform_ioremap_resource(pdev, 0);
0322     if (IS_ERR(ir->reg_base))
0323         return PTR_ERR(ir->reg_base);
0324 
0325     irq = platform_get_irq(pdev, 0);
0326     if (irq < 0)
0327         return -ENODEV;
0328 
0329     ir->dev = dev;
0330     ir->carrier = MIRTX_DEFAULT_CARRIER;
0331     ir->duty_cycle = MIRTX_DEFAULT_DUTY_CYCLE;
0332     init_completion(&ir->completion);
0333     spin_lock_init(&ir->lock);
0334 
0335     ret = meson_irtx_mod_clock_probe(ir, &clk_nr);
0336     if (ret) {
0337         dev_err(dev, "modulator clock setup failed\n");
0338         return ret;
0339     }
0340     meson_irtx_setup(ir, clk_nr);
0341 
0342     ret = devm_request_irq(dev, irq,
0343                    meson_irtx_irqhandler,
0344                    IRQF_TRIGGER_RISING,
0345                    DRIVER_NAME, ir);
0346     if (ret) {
0347         dev_err(dev, "irq request failed\n");
0348         return ret;
0349     }
0350 
0351     rc = rc_allocate_device(RC_DRIVER_IR_RAW_TX);
0352     if (!rc)
0353         return -ENOMEM;
0354 
0355     rc->driver_name = DRIVER_NAME;
0356     rc->device_name = DEVICE_NAME;
0357     rc->priv = ir;
0358 
0359     rc->tx_ir = meson_irtx_transmit;
0360     rc->s_tx_carrier = meson_irtx_set_carrier;
0361     rc->s_tx_duty_cycle = meson_irtx_set_duty_cycle;
0362 
0363     ret = rc_register_device(rc);
0364     if (ret < 0) {
0365         dev_err(dev, "rc_dev registration failed\n");
0366         rc_free_device(rc);
0367         return ret;
0368     }
0369 
0370     platform_set_drvdata(pdev, rc);
0371 
0372     return 0;
0373 }
0374 
0375 static int meson_irtx_remove(struct platform_device *pdev)
0376 {
0377     struct rc_dev *rc = platform_get_drvdata(pdev);
0378 
0379     rc_unregister_device(rc);
0380 
0381     return 0;
0382 }
0383 
0384 static const struct of_device_id meson_irtx_dt_match[] = {
0385     {
0386         .compatible = "amlogic,meson-g12a-ir-tx",
0387     },
0388     {},
0389 };
0390 MODULE_DEVICE_TABLE(of, meson_irtx_dt_match);
0391 
0392 static struct platform_driver meson_irtx_pd = {
0393     .remove = meson_irtx_remove,
0394     .driver = {
0395         .name = DRIVER_NAME,
0396         .of_match_table = meson_irtx_dt_match,
0397     },
0398 };
0399 
0400 module_platform_driver_probe(meson_irtx_pd, meson_irtx_probe);
0401 
0402 MODULE_DESCRIPTION("Meson IR TX driver");
0403 MODULE_AUTHOR("Viktor Prutyanov <viktor.prutyanov@phystech.edu>");
0404 MODULE_LICENSE("GPL");