Lines Matching +full:meson +full:- +full:ir +full:- +full:tx

1 // SPDX-License-Identifier: GPL-2.0-only
3 * meson-ir-tx.c - Amlogic Meson IR TX driver
20 #include <media/rc-core.h>
22 #define DEVICE_NAME "Meson IR TX"
23 #define DRIVER_NAME "meson-ir-tx"
39 #define IRB_DELAY_MASK (IRB_MAX_DELAY - 1)
51 #define IRB_MOD_COUNT(lo, hi) ((((lo) - 1) << 16) | ((hi) - 1))
79 static void meson_irtx_set_mod(struct meson_irtx *ir) in meson_irtx_set_mod() argument
81 unsigned int cnt = DIV_ROUND_CLOSEST(ir->clk_rate, ir->carrier); in meson_irtx_set_mod()
82 unsigned int pulse_cnt = DIV_ROUND_CLOSEST(cnt * ir->duty_cycle, 100); in meson_irtx_set_mod()
83 unsigned int space_cnt = cnt - pulse_cnt; in meson_irtx_set_mod()
85 dev_dbg(ir->dev, "F_mod = %uHz, T_mod = %luns, duty_cycle = %u%%\n", in meson_irtx_set_mod()
86 ir->carrier, NSEC_PER_SEC / ir->clk_rate * cnt, in meson_irtx_set_mod()
90 ir->reg_base + IRB_ADDR1); in meson_irtx_set_mod()
93 static void meson_irtx_setup(struct meson_irtx *ir, unsigned int clk_nr) in meson_irtx_setup() argument
96 * Disable the TX, set modulator clock tick and set initialize in meson_irtx_setup()
102 ir->reg_base + IRB_ADDR0); in meson_irtx_setup()
103 meson_irtx_set_mod(ir); in meson_irtx_setup()
104 writel(readl(ir->reg_base + IRB_ADDR0) & ~IRB_INIT_HIGH, in meson_irtx_setup()
105 ir->reg_base + IRB_ADDR0); in meson_irtx_setup()
107 ir->reg_base + IRB_ADDR3); in meson_irtx_setup()
108 writel(readl(ir->reg_base + IRB_ADDR0) | IRB_ENABLE, in meson_irtx_setup()
109 ir->reg_base + IRB_ADDR0); in meson_irtx_setup()
112 static u32 meson_irtx_prepare_pulse(struct meson_irtx *ir, unsigned int time) in meson_irtx_prepare_pulse() argument
116 unsigned int tb_us = DIV_ROUND_CLOSEST(USEC_PER_SEC, ir->carrier); in meson_irtx_prepare_pulse()
118 delay = (DIV_ROUND_CLOSEST(time, tb_us) - 1) & IRB_DELAY_MASK; in meson_irtx_prepare_pulse()
123 static u32 meson_irtx_prepare_space(struct meson_irtx *ir, unsigned int time) in meson_irtx_prepare_space() argument
140 delay = (DIV_ROUND_CLOSEST(time, tb_us) - 1) & IRB_DELAY_MASK; in meson_irtx_prepare_space()
145 static void meson_irtx_send_buffer(struct meson_irtx *ir) in meson_irtx_send_buffer() argument
148 unsigned int max_fifo_level = IRB_FIFO_LEN - MIRTX_FIFO_THD; in meson_irtx_send_buffer()
150 while (ir->buf_head < ir->buf_len && nr < max_fifo_level) { in meson_irtx_send_buffer()
151 writel(ir->buf[ir->buf_head], ir->reg_base + IRB_ADDR2); in meson_irtx_send_buffer()
153 ir->buf_head++; in meson_irtx_send_buffer()
158 static bool meson_irtx_check_buf(struct meson_irtx *ir, in meson_irtx_check_buf() argument
170 max_tb_us = USEC_PER_SEC / ir->carrier; in meson_irtx_check_buf()
181 static void meson_irtx_fill_buf(struct meson_irtx *ir, u32 *dst_buf, in meson_irtx_fill_buf() argument
188 dst_buf[i] = meson_irtx_prepare_pulse(ir, src_buf[i]); in meson_irtx_fill_buf()
190 dst_buf[i] = meson_irtx_prepare_space(ir, src_buf[i]); in meson_irtx_fill_buf()
197 struct meson_irtx *ir = data; in meson_irtx_irqhandler() local
199 writel(readl(ir->reg_base + IRB_ADDR3) & ~IRB_FIFO_THD_PENDING, in meson_irtx_irqhandler()
200 ir->reg_base + IRB_ADDR3); in meson_irtx_irqhandler()
202 if (completion_done(&ir->completion)) in meson_irtx_irqhandler()
205 spin_lock_irqsave(&ir->lock, flags); in meson_irtx_irqhandler()
206 if (ir->buf_head < ir->buf_len) in meson_irtx_irqhandler()
207 meson_irtx_send_buffer(ir); in meson_irtx_irqhandler()
209 complete(&ir->completion); in meson_irtx_irqhandler()
210 spin_unlock_irqrestore(&ir->lock, flags); in meson_irtx_irqhandler()
217 struct meson_irtx *ir = rc->priv; in meson_irtx_set_carrier() local
220 return -EINVAL; in meson_irtx_set_carrier()
222 ir->carrier = carrier; in meson_irtx_set_carrier()
223 meson_irtx_set_mod(ir); in meson_irtx_set_carrier()
230 struct meson_irtx *ir = rc->priv; in meson_irtx_set_duty_cycle() local
232 ir->duty_cycle = duty_cycle; in meson_irtx_set_duty_cycle()
233 meson_irtx_set_mod(ir); in meson_irtx_set_duty_cycle()
238 static void meson_irtx_update_buf(struct meson_irtx *ir, u32 *buf, in meson_irtx_update_buf() argument
241 ir->buf = buf; in meson_irtx_update_buf()
242 ir->buf_len = len; in meson_irtx_update_buf()
243 ir->buf_head = head; in meson_irtx_update_buf()
250 struct meson_irtx *ir = rc->priv; in meson_irtx_transmit() local
254 if (!meson_irtx_check_buf(ir, buf, len)) in meson_irtx_transmit()
255 return -EINVAL; in meson_irtx_transmit()
259 return -ENOMEM; in meson_irtx_transmit()
261 meson_irtx_fill_buf(ir, tx_buf, buf, len); in meson_irtx_transmit()
262 dev_dbg(ir->dev, "TX buffer filled, length = %u\n", len); in meson_irtx_transmit()
264 spin_lock_irqsave(&ir->lock, flags); in meson_irtx_transmit()
265 meson_irtx_update_buf(ir, tx_buf, len, 0); in meson_irtx_transmit()
266 reinit_completion(&ir->completion); in meson_irtx_transmit()
267 meson_irtx_send_buffer(ir); in meson_irtx_transmit()
268 spin_unlock_irqrestore(&ir->lock, flags); in meson_irtx_transmit()
270 if (!wait_for_completion_timeout(&ir->completion, in meson_irtx_transmit()
272 ret = -ETIMEDOUT; in meson_irtx_transmit()
274 spin_lock_irqsave(&ir->lock, flags); in meson_irtx_transmit()
275 kfree(ir->buf); in meson_irtx_transmit()
276 meson_irtx_update_buf(ir, NULL, 0, 0); in meson_irtx_transmit()
277 spin_unlock_irqrestore(&ir->lock, flags); in meson_irtx_transmit()
282 static int meson_irtx_mod_clock_probe(struct meson_irtx *ir, in meson_irtx_mod_clock_probe() argument
285 struct device_node *np = ir->dev->of_node; in meson_irtx_mod_clock_probe()
289 return -ENODEV; in meson_irtx_mod_clock_probe()
291 clock = devm_clk_get(ir->dev, "xtal"); in meson_irtx_mod_clock_probe()
293 return -ENODEV; in meson_irtx_mod_clock_probe()
296 ir->clk_rate = clk_get_rate(clock) / 3; in meson_irtx_mod_clock_probe()
298 if (ir->clk_rate < IRB_MOD_1US_CLK_RATE) { in meson_irtx_mod_clock_probe()
300 ir->clk_rate = IRB_MOD_1US_CLK_RATE; in meson_irtx_mod_clock_probe()
303 dev_info(ir->dev, "F_clk = %luHz\n", ir->clk_rate); in meson_irtx_mod_clock_probe()
310 struct device *dev = &pdev->dev; in meson_irtx_probe()
311 struct meson_irtx *ir; in meson_irtx_probe() local
317 ir = devm_kzalloc(dev, sizeof(*ir), GFP_KERNEL); in meson_irtx_probe()
318 if (!ir) in meson_irtx_probe()
319 return -ENOMEM; in meson_irtx_probe()
321 ir->reg_base = devm_platform_ioremap_resource(pdev, 0); in meson_irtx_probe()
322 if (IS_ERR(ir->reg_base)) in meson_irtx_probe()
323 return PTR_ERR(ir->reg_base); in meson_irtx_probe()
327 return -ENODEV; in meson_irtx_probe()
329 ir->dev = dev; in meson_irtx_probe()
330 ir->carrier = MIRTX_DEFAULT_CARRIER; in meson_irtx_probe()
331 ir->duty_cycle = MIRTX_DEFAULT_DUTY_CYCLE; in meson_irtx_probe()
332 init_completion(&ir->completion); in meson_irtx_probe()
333 spin_lock_init(&ir->lock); in meson_irtx_probe()
335 ret = meson_irtx_mod_clock_probe(ir, &clk_nr); in meson_irtx_probe()
339 meson_irtx_setup(ir, clk_nr); in meson_irtx_probe()
344 DRIVER_NAME, ir); in meson_irtx_probe()
350 return -ENOMEM; in meson_irtx_probe()
352 rc->driver_name = DRIVER_NAME; in meson_irtx_probe()
353 rc->device_name = DEVICE_NAME; in meson_irtx_probe()
354 rc->priv = ir; in meson_irtx_probe()
356 rc->tx_ir = meson_irtx_transmit; in meson_irtx_probe()
357 rc->s_tx_carrier = meson_irtx_set_carrier; in meson_irtx_probe()
358 rc->s_tx_duty_cycle = meson_irtx_set_duty_cycle; in meson_irtx_probe()
371 .compatible = "amlogic,meson-g12a-ir-tx",
386 MODULE_DESCRIPTION("Meson IR TX driver");