1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2017 Sean Young <sean@mess.org>
6 #include <linux/kernel.h>
7 #include <linux/module.h>
9 #include <linux/delay.h>
10 #include <linux/slab.h>
12 #include <linux/platform_device.h>
13 #include <media/rc-core.h>
15 #define DRIVER_NAME "pwm-ir-tx"
16 #define DEVICE_NAME "PWM IR Transmitter"
19 struct pwm_device
*pwm
;
21 unsigned int duty_cycle
;
24 static const struct of_device_id pwm_ir_of_match
[] = {
25 { .compatible
= "pwm-ir-tx", },
28 MODULE_DEVICE_TABLE(of
, pwm_ir_of_match
);
30 static int pwm_ir_set_duty_cycle(struct rc_dev
*dev
, u32 duty_cycle
)
32 struct pwm_ir
*pwm_ir
= dev
->priv
;
34 pwm_ir
->duty_cycle
= duty_cycle
;
39 static int pwm_ir_set_carrier(struct rc_dev
*dev
, u32 carrier
)
41 struct pwm_ir
*pwm_ir
= dev
->priv
;
46 pwm_ir
->carrier
= carrier
;
51 static int pwm_ir_tx(struct rc_dev
*dev
, unsigned int *txbuf
,
54 struct pwm_ir
*pwm_ir
= dev
->priv
;
55 struct pwm_device
*pwm
= pwm_ir
->pwm
;
60 period
= DIV_ROUND_CLOSEST(NSEC_PER_SEC
, pwm_ir
->carrier
);
61 duty
= DIV_ROUND_CLOSEST(pwm_ir
->duty_cycle
* period
, 100);
63 pwm_config(pwm
, duty
, period
);
67 for (i
= 0; i
< count
; i
++) {
73 edge
= ktime_add_us(edge
, txbuf
[i
]);
74 delta
= ktime_us_delta(edge
, ktime_get());
76 usleep_range(delta
, delta
+ 10);
84 static int pwm_ir_probe(struct platform_device
*pdev
)
86 struct pwm_ir
*pwm_ir
;
90 pwm_ir
= devm_kmalloc(&pdev
->dev
, sizeof(*pwm_ir
), GFP_KERNEL
);
94 pwm_ir
->pwm
= devm_pwm_get(&pdev
->dev
, NULL
);
95 if (IS_ERR(pwm_ir
->pwm
))
96 return PTR_ERR(pwm_ir
->pwm
);
98 pwm_ir
->carrier
= 38000;
99 pwm_ir
->duty_cycle
= 50;
101 rcdev
= devm_rc_allocate_device(&pdev
->dev
, RC_DRIVER_IR_RAW_TX
);
105 rcdev
->priv
= pwm_ir
;
106 rcdev
->driver_name
= DRIVER_NAME
;
107 rcdev
->device_name
= DEVICE_NAME
;
108 rcdev
->tx_ir
= pwm_ir_tx
;
109 rcdev
->s_tx_duty_cycle
= pwm_ir_set_duty_cycle
;
110 rcdev
->s_tx_carrier
= pwm_ir_set_carrier
;
112 rc
= devm_rc_register_device(&pdev
->dev
, rcdev
);
114 dev_err(&pdev
->dev
, "failed to register rc device\n");
119 static struct platform_driver pwm_ir_driver
= {
120 .probe
= pwm_ir_probe
,
123 .of_match_table
= of_match_ptr(pwm_ir_of_match
),
126 module_platform_driver(pwm_ir_driver
);
128 MODULE_DESCRIPTION("PWM IR Transmitter");
129 MODULE_AUTHOR("Sean Young <sean@mess.org>");
130 MODULE_LICENSE("GPL");