1 // SPDX-License-Identifier: GPL-2.0-only
3 * meson-ir-tx.c - Amlogic Meson IR TX driver
5 * Copyright (c) 2021, SberDevices. All Rights Reserved.
7 * Author: Viktor Prutyanov <viktor.prutyanov@phystech.edu>
10 #include <linux/device.h>
11 #include <linux/module.h>
12 #include <linux/sched.h>
13 #include <linux/platform_device.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>
22 #define DEVICE_NAME "Meson IR TX"
23 #define DRIVER_NAME "meson-ir-tx"
25 #define MIRTX_DEFAULT_CARRIER 38000
26 #define MIRTX_DEFAULT_DUTY_CYCLE 50
27 #define MIRTX_FIFO_THD 32
29 #define IRB_MOD_1US_CLK_RATE 1000000
31 #define IRB_FIFO_LEN 128
38 #define IRB_MAX_DELAY (1 << 10)
39 #define IRB_DELAY_MASK (IRB_MAX_DELAY - 1)
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)
50 /* IRCTRL_IR_BLASTER_ADDR2 */
51 #define IRB_MOD_COUNT(lo, hi) ((((lo) - 1) << 16) | ((hi) - 1))
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)
61 /* IRCTRL_IR_BLASTER_ADDR3 */
62 #define IRB_FIFO_THD_PENDING BIT(16)
63 #define IRB_FIFO_IRQ_ENABLE BIT(8)
67 void __iomem
*reg_base
;
70 unsigned int buf_head
;
72 unsigned int duty_cycle
;
75 struct completion completion
;
76 unsigned long clk_rate
;
79 static void meson_irtx_set_mod(struct meson_irtx
*ir
)
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
;
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
);
89 writel(IRB_MOD_COUNT(pulse_cnt
, space_cnt
),
90 ir
->reg_base
+ IRB_ADDR1
);
93 static void meson_irtx_setup(struct meson_irtx
*ir
, unsigned int clk_nr
)
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.
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
);
112 static u32
meson_irtx_prepare_pulse(struct meson_irtx
*ir
, unsigned int time
)
115 unsigned int tb
= IRB_TB_MOD_CLK
;
116 unsigned int tb_us
= DIV_ROUND_CLOSEST(USEC_PER_SEC
, ir
->carrier
);
118 delay
= (DIV_ROUND_CLOSEST(time
, tb_us
) - 1) & IRB_DELAY_MASK
;
120 return ((IRB_WRITE_FIFO
| IRB_MOD_ENABLE
) | tb
| delay
);
123 static u32
meson_irtx_prepare_space(struct meson_irtx
*ir
, unsigned int time
)
126 unsigned int tb
= IRB_TB_100US
;
127 unsigned int tb_us
= 100;
129 if (time
<= IRB_MAX_DELAY
) {
132 } else if (time
<= 10 * IRB_MAX_DELAY
) {
135 } else if (time
<= 100 * IRB_MAX_DELAY
) {
140 delay
= (DIV_ROUND_CLOSEST(time
, tb_us
) - 1) & IRB_DELAY_MASK
;
142 return ((IRB_WRITE_FIFO
& ~IRB_MOD_ENABLE
) | tb
| delay
);
145 static void meson_irtx_send_buffer(struct meson_irtx
*ir
)
148 unsigned int max_fifo_level
= IRB_FIFO_LEN
- MIRTX_FIFO_THD
;
150 while (ir
->buf_head
< ir
->buf_len
&& nr
< max_fifo_level
) {
151 writel(ir
->buf
[ir
->buf_head
], ir
->reg_base
+ IRB_ADDR2
);
158 static bool meson_irtx_check_buf(struct meson_irtx
*ir
,
159 unsigned int *buf
, unsigned int len
)
163 for (i
= 0; i
< len
; i
++) {
164 unsigned int max_tb_us
;
166 * Max space timebase is 100 us.
167 * Pulse timebase equals to carrier period.
170 max_tb_us
= USEC_PER_SEC
/ ir
->carrier
;
174 if (buf
[i
] >= max_tb_us
* IRB_MAX_DELAY
)
181 static void meson_irtx_fill_buf(struct meson_irtx
*ir
, u32
*dst_buf
,
182 unsigned int *src_buf
, unsigned int len
)
186 for (i
= 0; i
< len
; i
++) {
188 dst_buf
[i
] = meson_irtx_prepare_pulse(ir
, src_buf
[i
]);
190 dst_buf
[i
] = meson_irtx_prepare_space(ir
, src_buf
[i
]);
194 static irqreturn_t
meson_irtx_irqhandler(int irq
, void *data
)
197 struct meson_irtx
*ir
= data
;
199 writel(readl(ir
->reg_base
+ IRB_ADDR3
) & ~IRB_FIFO_THD_PENDING
,
200 ir
->reg_base
+ IRB_ADDR3
);
202 if (completion_done(&ir
->completion
))
205 spin_lock_irqsave(&ir
->lock
, flags
);
206 if (ir
->buf_head
< ir
->buf_len
)
207 meson_irtx_send_buffer(ir
);
209 complete(&ir
->completion
);
210 spin_unlock_irqrestore(&ir
->lock
, flags
);
215 static int meson_irtx_set_carrier(struct rc_dev
*rc
, u32 carrier
)
217 struct meson_irtx
*ir
= rc
->priv
;
222 ir
->carrier
= carrier
;
223 meson_irtx_set_mod(ir
);
228 static int meson_irtx_set_duty_cycle(struct rc_dev
*rc
, u32 duty_cycle
)
230 struct meson_irtx
*ir
= rc
->priv
;
232 ir
->duty_cycle
= duty_cycle
;
233 meson_irtx_set_mod(ir
);
238 static void meson_irtx_update_buf(struct meson_irtx
*ir
, u32
*buf
,
239 unsigned int len
, unsigned int head
)
246 static int meson_irtx_transmit(struct rc_dev
*rc
, unsigned int *buf
,
250 struct meson_irtx
*ir
= rc
->priv
;
254 if (!meson_irtx_check_buf(ir
, buf
, len
))
257 tx_buf
= kmalloc_array(len
, sizeof(u32
), GFP_KERNEL
);
261 meson_irtx_fill_buf(ir
, tx_buf
, buf
, len
);
262 dev_dbg(ir
->dev
, "TX buffer filled, length = %u\n", len
);
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
);
270 if (!wait_for_completion_timeout(&ir
->completion
,
271 usecs_to_jiffies(IR_MAX_DURATION
)))
274 spin_lock_irqsave(&ir
->lock
, flags
);
276 meson_irtx_update_buf(ir
, NULL
, 0, 0);
277 spin_unlock_irqrestore(&ir
->lock
, flags
);
282 static int meson_irtx_mod_clock_probe(struct meson_irtx
*ir
,
283 unsigned int *clk_nr
)
285 struct device_node
*np
= ir
->dev
->of_node
;
291 clock
= devm_clk_get(ir
->dev
, "xtal");
292 if (IS_ERR(clock
) || clk_prepare_enable(clock
))
295 *clk_nr
= IRB_MOD_XTAL3_CLK
;
296 ir
->clk_rate
= clk_get_rate(clock
) / 3;
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
;
303 dev_info(ir
->dev
, "F_clk = %luHz\n", ir
->clk_rate
);
308 static int meson_irtx_probe(struct platform_device
*pdev
)
310 struct device
*dev
= &pdev
->dev
;
311 struct meson_irtx
*ir
;
317 ir
= devm_kzalloc(dev
, sizeof(*ir
), GFP_KERNEL
);
321 ir
->reg_base
= devm_platform_ioremap_resource(pdev
, 0);
322 if (IS_ERR(ir
->reg_base
))
323 return PTR_ERR(ir
->reg_base
);
325 irq
= platform_get_irq(pdev
, 0);
330 ir
->carrier
= MIRTX_DEFAULT_CARRIER
;
331 ir
->duty_cycle
= MIRTX_DEFAULT_DUTY_CYCLE
;
332 init_completion(&ir
->completion
);
333 spin_lock_init(&ir
->lock
);
335 ret
= meson_irtx_mod_clock_probe(ir
, &clk_nr
);
337 return dev_err_probe(dev
, ret
, "modulator clock setup failed\n");
339 meson_irtx_setup(ir
, clk_nr
);
341 ret
= devm_request_irq(dev
, irq
,
342 meson_irtx_irqhandler
,
346 return dev_err_probe(dev
, ret
, "irq request failed\n");
348 rc
= rc_allocate_device(RC_DRIVER_IR_RAW_TX
);
352 rc
->driver_name
= DRIVER_NAME
;
353 rc
->device_name
= DEVICE_NAME
;
356 rc
->tx_ir
= meson_irtx_transmit
;
357 rc
->s_tx_carrier
= meson_irtx_set_carrier
;
358 rc
->s_tx_duty_cycle
= meson_irtx_set_duty_cycle
;
360 ret
= devm_rc_register_device(dev
, rc
);
363 return dev_err_probe(dev
, ret
, "rc_dev registration failed\n");
369 static const struct of_device_id meson_irtx_dt_match
[] = {
371 .compatible
= "amlogic,meson-g12a-ir-tx",
375 MODULE_DEVICE_TABLE(of
, meson_irtx_dt_match
);
377 static struct platform_driver meson_irtx_pd
= {
378 .probe
= meson_irtx_probe
,
381 .of_match_table
= meson_irtx_dt_match
,
384 module_platform_driver(meson_irtx_pd
);
386 MODULE_DESCRIPTION("Meson IR TX driver");
387 MODULE_AUTHOR("Viktor Prutyanov <viktor.prutyanov@phystech.edu>");
388 MODULE_LICENSE("GPL");