2 * Copyright (C) 2017 Sean Young <sean@mess.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2, or
6 * (at your option) any later version.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
14 #include <linux/kernel.h>
15 #include <linux/module.h>
16 #include <linux/pwm.h>
17 #include <linux/delay.h>
18 #include <linux/slab.h>
20 #include <linux/platform_device.h>
21 #include <media/rc-core.h>
23 #define DRIVER_NAME "pwm-ir-tx"
24 #define DEVICE_NAME "PWM IR Transmitter"
27 struct pwm_device
*pwm
;
29 unsigned int duty_cycle
;
32 static const struct of_device_id pwm_ir_of_match
[] = {
33 { .compatible
= "pwm-ir-tx", },
36 MODULE_DEVICE_TABLE(of
, pwm_ir_of_match
);
38 static int pwm_ir_set_duty_cycle(struct rc_dev
*dev
, u32 duty_cycle
)
40 struct pwm_ir
*pwm_ir
= dev
->priv
;
42 pwm_ir
->duty_cycle
= duty_cycle
;
47 static int pwm_ir_set_carrier(struct rc_dev
*dev
, u32 carrier
)
49 struct pwm_ir
*pwm_ir
= dev
->priv
;
54 pwm_ir
->carrier
= carrier
;
59 static int pwm_ir_tx(struct rc_dev
*dev
, unsigned int *txbuf
,
62 struct pwm_ir
*pwm_ir
= dev
->priv
;
63 struct pwm_device
*pwm
= pwm_ir
->pwm
;
68 period
= DIV_ROUND_CLOSEST(NSEC_PER_SEC
, pwm_ir
->carrier
);
69 duty
= DIV_ROUND_CLOSEST(pwm_ir
->duty_cycle
* period
, 100);
71 pwm_config(pwm
, duty
, period
);
75 for (i
= 0; i
< count
; i
++) {
81 edge
= ktime_add_us(edge
, txbuf
[i
]);
82 delta
= ktime_us_delta(edge
, ktime_get());
84 usleep_range(delta
, delta
+ 10);
92 static int pwm_ir_probe(struct platform_device
*pdev
)
94 struct pwm_ir
*pwm_ir
;
98 pwm_ir
= devm_kmalloc(&pdev
->dev
, sizeof(*pwm_ir
), GFP_KERNEL
);
102 pwm_ir
->pwm
= devm_pwm_get(&pdev
->dev
, NULL
);
103 if (IS_ERR(pwm_ir
->pwm
))
104 return PTR_ERR(pwm_ir
->pwm
);
106 pwm_ir
->carrier
= 38000;
107 pwm_ir
->duty_cycle
= 50;
109 rcdev
= devm_rc_allocate_device(&pdev
->dev
, RC_DRIVER_IR_RAW_TX
);
113 rcdev
->priv
= pwm_ir
;
114 rcdev
->driver_name
= DRIVER_NAME
;
115 rcdev
->device_name
= DEVICE_NAME
;
116 rcdev
->tx_ir
= pwm_ir_tx
;
117 rcdev
->s_tx_duty_cycle
= pwm_ir_set_duty_cycle
;
118 rcdev
->s_tx_carrier
= pwm_ir_set_carrier
;
120 rc
= devm_rc_register_device(&pdev
->dev
, rcdev
);
122 dev_err(&pdev
->dev
, "failed to register rc device\n");
127 static struct platform_driver pwm_ir_driver
= {
128 .probe
= pwm_ir_probe
,
131 .of_match_table
= of_match_ptr(pwm_ir_of_match
),
134 module_platform_driver(pwm_ir_driver
);
136 MODULE_DESCRIPTION("PWM IR Transmitter");
137 MODULE_AUTHOR("Sean Young <sean@mess.org>");
138 MODULE_LICENSE("GPL");