linux/drivers/media/rc/meson-ir-tx.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/**
   3 * meson-ir-tx.c - Amlogic Meson IR TX driver
   4 *
   5 * Copyright (c) 2021, SberDevices. All Rights Reserved.
   6 *
   7 * Author: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
   8 */
   9
  10#include <linux/device.h>
  11#include <linux/module.h>
  12#include <linux/sched.h>
  13#include <linux/platform_device.h>
  14#include <linux/of.h>
  15#include <linux/interrupt.h>
  16#include <linux/spinlock.h>
  17#include <linux/of_irq.h>
  18#include <linux/clk.h>
  19#include <linux/slab.h>
  20#include <media/rc-core.h>
  21
  22#define DEVICE_NAME     "Meson IR TX"
  23#define DRIVER_NAME     "meson-ir-tx"
  24
  25#define MIRTX_DEFAULT_CARRIER           38000
  26#define MIRTX_DEFAULT_DUTY_CYCLE        50
  27#define MIRTX_FIFO_THD                  32
  28
  29#define IRB_MOD_1US_CLK_RATE    1000000
  30
  31#define IRB_FIFO_LEN    128
  32
  33#define IRB_ADDR0       0x0
  34#define IRB_ADDR1       0x4
  35#define IRB_ADDR2       0x8
  36#define IRB_ADDR3       0xc
  37
  38#define IRB_MAX_DELAY   (1 << 10)
  39#define IRB_DELAY_MASK  (IRB_MAX_DELAY - 1)
  40
  41/* IRCTRL_IR_BLASTER_ADDR0 */
  42#define IRB_MOD_CLK(x)          ((x) << 12)
  43#define IRB_MOD_SYS_CLK         0
  44#define IRB_MOD_XTAL3_CLK       1
  45#define IRB_MOD_1US_CLK         2
  46#define IRB_MOD_10US_CLK        3
  47#define IRB_INIT_HIGH           BIT(2)
  48#define IRB_ENABLE              BIT(0)
  49
  50/* IRCTRL_IR_BLASTER_ADDR2 */
  51#define IRB_MOD_COUNT(lo, hi)   ((((lo) - 1) << 16) | ((hi) - 1))
  52
  53/* IRCTRL_IR_BLASTER_ADDR2 */
  54#define IRB_WRITE_FIFO  BIT(16)
  55#define IRB_MOD_ENABLE  BIT(12)
  56#define IRB_TB_1US      (0x0 << 10)
  57#define IRB_TB_10US     (0x1 << 10)
  58#define IRB_TB_100US    (0x2 << 10)
  59#define IRB_TB_MOD_CLK  (0x3 << 10)
  60
  61/* IRCTRL_IR_BLASTER_ADDR3 */
  62#define IRB_FIFO_THD_PENDING    BIT(16)
  63#define IRB_FIFO_IRQ_ENABLE     BIT(8)
  64
  65struct meson_irtx {
  66        struct device *dev;
  67        void __iomem *reg_base;
  68        u32 *buf;
  69        unsigned int buf_len;
  70        unsigned int buf_head;
  71        unsigned int carrier;
  72        unsigned int duty_cycle;
  73        /* Locks buf */
  74        spinlock_t lock;
  75        struct completion completion;
  76        unsigned long clk_rate;
  77};
  78
  79static void meson_irtx_set_mod(struct meson_irtx *ir)
  80{
  81        unsigned int cnt = DIV_ROUND_CLOSEST(ir->clk_rate, ir->carrier);
  82        unsigned int pulse_cnt = DIV_ROUND_CLOSEST(cnt * ir->duty_cycle, 100);
  83        unsigned int space_cnt = cnt - pulse_cnt;
  84
  85        dev_dbg(ir->dev, "F_mod = %uHz, T_mod = %luns, duty_cycle = %u%%\n",
  86                ir->carrier, NSEC_PER_SEC / ir->clk_rate * cnt,
  87                100 * pulse_cnt / cnt);
  88
  89        writel(IRB_MOD_COUNT(pulse_cnt, space_cnt),
  90               ir->reg_base + IRB_ADDR1);
  91}
  92
  93static void meson_irtx_setup(struct meson_irtx *ir, unsigned int clk_nr)
  94{
  95        /*
  96         * Disable the TX, set modulator clock tick and set initialize
  97         * output to be high. Set up carrier frequency and duty cycle. Then
  98         * unset initialize output. Enable FIFO interrupt, set FIFO interrupt
  99         * threshold. Finally, enable the transmitter back.
 100         */
 101        writel(~IRB_ENABLE & (IRB_MOD_CLK(clk_nr) | IRB_INIT_HIGH),
 102               ir->reg_base + IRB_ADDR0);
 103        meson_irtx_set_mod(ir);
 104        writel(readl(ir->reg_base + IRB_ADDR0) & ~IRB_INIT_HIGH,
 105               ir->reg_base + IRB_ADDR0);
 106        writel(IRB_FIFO_IRQ_ENABLE | MIRTX_FIFO_THD,
 107               ir->reg_base + IRB_ADDR3);
 108        writel(readl(ir->reg_base + IRB_ADDR0) | IRB_ENABLE,
 109               ir->reg_base + IRB_ADDR0);
 110}
 111
 112static u32 meson_irtx_prepare_pulse(struct meson_irtx *ir, unsigned int time)
 113{
 114        unsigned int delay;
 115        unsigned int tb = IRB_TB_MOD_CLK;
 116        unsigned int tb_us = DIV_ROUND_CLOSEST(USEC_PER_SEC, ir->carrier);
 117
 118        delay = (DIV_ROUND_CLOSEST(time, tb_us) - 1) & IRB_DELAY_MASK;
 119
 120        return ((IRB_WRITE_FIFO | IRB_MOD_ENABLE) | tb | delay);
 121}
 122
 123static u32 meson_irtx_prepare_space(struct meson_irtx *ir, unsigned int time)
 124{
 125        unsigned int delay;
 126        unsigned int tb = IRB_TB_100US;
 127        unsigned int tb_us = 100;
 128
 129        if (time <= IRB_MAX_DELAY) {
 130                tb = IRB_TB_1US;
 131                tb_us = 1;
 132        } else if (time <= 10 * IRB_MAX_DELAY) {
 133                tb = IRB_TB_10US;
 134                tb_us = 10;
 135        } else if (time <= 100 * IRB_MAX_DELAY) {
 136                tb = IRB_TB_100US;
 137                tb_us = 100;
 138        }
 139
 140        delay = (DIV_ROUND_CLOSEST(time, tb_us) - 1) & IRB_DELAY_MASK;
 141
 142        return ((IRB_WRITE_FIFO & ~IRB_MOD_ENABLE) | tb | delay);
 143}
 144
 145static void meson_irtx_send_buffer(struct meson_irtx *ir)
 146{
 147        unsigned int nr = 0;
 148        unsigned int max_fifo_level = IRB_FIFO_LEN - MIRTX_FIFO_THD;
 149
 150        while (ir->buf_head < ir->buf_len && nr < max_fifo_level) {
 151                writel(ir->buf[ir->buf_head], ir->reg_base + IRB_ADDR2);
 152
 153                ir->buf_head++;
 154                nr++;
 155        }
 156}
 157
 158static bool meson_irtx_check_buf(struct meson_irtx *ir,
 159                                 unsigned int *buf, unsigned int len)
 160{
 161        unsigned int i;
 162
 163        for (i = 0; i < len; i++) {
 164                unsigned int max_tb_us;
 165                /*
 166                 * Max space timebase is 100 us.
 167                 * Pulse timebase equals to carrier period.
 168                 */
 169                if (i % 2 == 0)
 170                        max_tb_us = USEC_PER_SEC / ir->carrier;
 171                else
 172                        max_tb_us = 100;
 173
 174                if (buf[i] >= max_tb_us * IRB_MAX_DELAY)
 175                        return false;
 176        }
 177
 178        return true;
 179}
 180
 181static void meson_irtx_fill_buf(struct meson_irtx *ir, u32 *dst_buf,
 182                                unsigned int *src_buf, unsigned int len)
 183{
 184        unsigned int i;
 185
 186        for (i = 0; i < len; i++) {
 187                if (i % 2 == 0)
 188                        dst_buf[i] = meson_irtx_prepare_pulse(ir, src_buf[i]);
 189                else
 190                        dst_buf[i] = meson_irtx_prepare_space(ir, src_buf[i]);
 191        }
 192}
 193
 194static irqreturn_t meson_irtx_irqhandler(int irq, void *data)
 195{
 196        unsigned long flags;
 197        struct meson_irtx *ir = data;
 198
 199        writel(readl(ir->reg_base + IRB_ADDR3) & ~IRB_FIFO_THD_PENDING,
 200               ir->reg_base + IRB_ADDR3);
 201
 202        if (completion_done(&ir->completion))
 203                return IRQ_HANDLED;
 204
 205        spin_lock_irqsave(&ir->lock, flags);
 206        if (ir->buf_head < ir->buf_len)
 207                meson_irtx_send_buffer(ir);
 208        else
 209                complete(&ir->completion);
 210        spin_unlock_irqrestore(&ir->lock, flags);
 211
 212        return IRQ_HANDLED;
 213}
 214
 215static int meson_irtx_set_carrier(struct rc_dev *rc, u32 carrier)
 216{
 217        struct meson_irtx *ir = rc->priv;
 218
 219        if (carrier == 0)
 220                return -EINVAL;
 221
 222        ir->carrier = carrier;
 223        meson_irtx_set_mod(ir);
 224
 225        return 0;
 226}
 227
 228static int meson_irtx_set_duty_cycle(struct rc_dev *rc, u32 duty_cycle)
 229{
 230        struct meson_irtx *ir = rc->priv;
 231
 232        ir->duty_cycle = duty_cycle;
 233        meson_irtx_set_mod(ir);
 234
 235        return 0;
 236}
 237
 238static void meson_irtx_update_buf(struct meson_irtx *ir, u32 *buf,
 239                                  unsigned int len, unsigned int head)
 240{
 241        ir->buf = buf;
 242        ir->buf_len = len;
 243        ir->buf_head = head;
 244}
 245
 246static int meson_irtx_transmit(struct rc_dev *rc, unsigned int *buf,
 247                               unsigned int len)
 248{
 249        unsigned long flags;
 250        struct meson_irtx *ir = rc->priv;
 251        u32 *tx_buf;
 252        int ret = len;
 253
 254        if (!meson_irtx_check_buf(ir, buf, len))
 255                return -EINVAL;
 256
 257        tx_buf = kmalloc_array(len, sizeof(u32), GFP_KERNEL);
 258        if (!tx_buf)
 259                return -ENOMEM;
 260
 261        meson_irtx_fill_buf(ir, tx_buf, buf, len);
 262        dev_dbg(ir->dev, "TX buffer filled, length = %u\n", len);
 263
 264        spin_lock_irqsave(&ir->lock, flags);
 265        meson_irtx_update_buf(ir, tx_buf, len, 0);
 266        reinit_completion(&ir->completion);
 267        meson_irtx_send_buffer(ir);
 268        spin_unlock_irqrestore(&ir->lock, flags);
 269
 270        if (!wait_for_completion_timeout(&ir->completion,
 271                                         usecs_to_jiffies(IR_MAX_DURATION)))
 272                ret = -ETIMEDOUT;
 273
 274        spin_lock_irqsave(&ir->lock, flags);
 275        kfree(ir->buf);
 276        meson_irtx_update_buf(ir, NULL, 0, 0);
 277        spin_unlock_irqrestore(&ir->lock, flags);
 278
 279        return ret;
 280}
 281
 282static int meson_irtx_mod_clock_probe(struct meson_irtx *ir,
 283                                      unsigned int *clk_nr)
 284{
 285        struct device_node *np = ir->dev->of_node;
 286        struct clk *clock;
 287
 288        if (!np)
 289                return -ENODEV;
 290
 291        clock = devm_clk_get(ir->dev, "xtal");
 292        if (IS_ERR(clock) || clk_prepare_enable(clock))
 293                return -ENODEV;
 294
 295        *clk_nr = IRB_MOD_XTAL3_CLK;
 296        ir->clk_rate = clk_get_rate(clock) / 3;
 297
 298        if (ir->clk_rate < IRB_MOD_1US_CLK_RATE) {
 299                *clk_nr = IRB_MOD_1US_CLK;
 300                ir->clk_rate = IRB_MOD_1US_CLK_RATE;
 301        }
 302
 303        dev_info(ir->dev, "F_clk = %luHz\n", ir->clk_rate);
 304
 305        return 0;
 306}
 307
 308static int __init meson_irtx_probe(struct platform_device *pdev)
 309{
 310        struct device *dev = &pdev->dev;
 311        struct meson_irtx *ir;
 312        struct rc_dev *rc;
 313        int irq;
 314        unsigned int clk_nr;
 315        int ret;
 316
 317        ir = devm_kzalloc(dev, sizeof(*ir), GFP_KERNEL);
 318        if (!ir)
 319                return -ENOMEM;
 320
 321        ir->reg_base = devm_platform_ioremap_resource(pdev, 0);
 322        if (IS_ERR(ir->reg_base))
 323                return PTR_ERR(ir->reg_base);
 324
 325        irq = platform_get_irq(pdev, 0);
 326        if (irq < 0) {
 327                dev_err(dev, "no irq resource found\n");
 328                return -ENODEV;
 329        }
 330
 331        ir->dev = dev;
 332        ir->carrier = MIRTX_DEFAULT_CARRIER;
 333        ir->duty_cycle = MIRTX_DEFAULT_DUTY_CYCLE;
 334        init_completion(&ir->completion);
 335        spin_lock_init(&ir->lock);
 336
 337        ret = meson_irtx_mod_clock_probe(ir, &clk_nr);
 338        if (ret) {
 339                dev_err(dev, "modulator clock setup failed\n");
 340                return ret;
 341        }
 342        meson_irtx_setup(ir, clk_nr);
 343
 344        ret = devm_request_irq(dev, irq,
 345                               meson_irtx_irqhandler,
 346                               IRQF_TRIGGER_RISING,
 347                               DRIVER_NAME, ir);
 348        if (ret) {
 349                dev_err(dev, "irq request failed\n");
 350                return ret;
 351        }
 352
 353        rc = rc_allocate_device(RC_DRIVER_IR_RAW_TX);
 354        if (!rc)
 355                return -ENOMEM;
 356
 357        rc->driver_name = DRIVER_NAME;
 358        rc->device_name = DEVICE_NAME;
 359        rc->priv = ir;
 360
 361        rc->tx_ir = meson_irtx_transmit;
 362        rc->s_tx_carrier = meson_irtx_set_carrier;
 363        rc->s_tx_duty_cycle = meson_irtx_set_duty_cycle;
 364
 365        ret = rc_register_device(rc);
 366        if (ret < 0) {
 367                dev_err(dev, "rc_dev registration failed\n");
 368                rc_free_device(rc);
 369                return ret;
 370        }
 371
 372        platform_set_drvdata(pdev, rc);
 373
 374        return 0;
 375}
 376
 377static int meson_irtx_remove(struct platform_device *pdev)
 378{
 379        struct rc_dev *rc = platform_get_drvdata(pdev);
 380
 381        rc_unregister_device(rc);
 382
 383        return 0;
 384}
 385
 386static const struct of_device_id meson_irtx_dt_match[] = {
 387        {
 388                .compatible = "amlogic,meson-g12a-ir-tx",
 389        },
 390        {},
 391};
 392MODULE_DEVICE_TABLE(of, meson_irtx_dt_match);
 393
 394static struct platform_driver meson_irtx_pd = {
 395        .remove = meson_irtx_remove,
 396        .driver = {
 397                .name = DRIVER_NAME,
 398                .owner  = THIS_MODULE,
 399                .of_match_table = meson_irtx_dt_match,
 400        },
 401};
 402
 403module_platform_driver_probe(meson_irtx_pd, meson_irtx_probe);
 404
 405MODULE_DESCRIPTION("Meson IR TX driver");
 406MODULE_AUTHOR("Viktor Prutyanov <viktor.prutyanov@phystech.edu>");
 407MODULE_LICENSE("GPL");
 408