root/drivers/media/rc/st_rc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. st_rc_send_lirc_timeout
  2. st_rc_rx_interrupt
  3. st_rc_hardware_init
  4. st_rc_remove
  5. st_rc_open
  6. st_rc_close
  7. st_rc_probe
  8. st_rc_suspend
  9. st_rc_resume

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright (C) 2013 STMicroelectronics Limited
   4  * Author: Srinivas Kandagatla <srinivas.kandagatla@st.com>
   5  */
   6 #include <linux/kernel.h>
   7 #include <linux/clk.h>
   8 #include <linux/interrupt.h>
   9 #include <linux/module.h>
  10 #include <linux/of.h>
  11 #include <linux/platform_device.h>
  12 #include <linux/reset.h>
  13 #include <media/rc-core.h>
  14 #include <linux/pinctrl/consumer.h>
  15 #include <linux/pm_wakeirq.h>
  16 
  17 struct st_rc_device {
  18         struct device                   *dev;
  19         int                             irq;
  20         int                             irq_wake;
  21         struct clk                      *sys_clock;
  22         void __iomem                    *base;  /* Register base address */
  23         void __iomem                    *rx_base;/* RX Register base address */
  24         struct rc_dev                   *rdev;
  25         bool                            overclocking;
  26         int                             sample_mult;
  27         int                             sample_div;
  28         bool                            rxuhfmode;
  29         struct  reset_control           *rstc;
  30 };
  31 
  32 /* Registers */
  33 #define IRB_SAMPLE_RATE_COMM    0x64    /* sample freq divisor*/
  34 #define IRB_CLOCK_SEL           0x70    /* clock select       */
  35 #define IRB_CLOCK_SEL_STATUS    0x74    /* clock status       */
  36 /* IRB IR/UHF receiver registers */
  37 #define IRB_RX_ON               0x40    /* pulse time capture */
  38 #define IRB_RX_SYS              0X44    /* sym period capture */
  39 #define IRB_RX_INT_EN           0x48    /* IRQ enable (R/W)   */
  40 #define IRB_RX_INT_STATUS       0x4c    /* IRQ status (R/W)   */
  41 #define IRB_RX_EN               0x50    /* Receive enable     */
  42 #define IRB_MAX_SYM_PERIOD      0x54    /* max sym value      */
  43 #define IRB_RX_INT_CLEAR        0x58    /* overrun status     */
  44 #define IRB_RX_STATUS           0x6c    /* receive status     */
  45 #define IRB_RX_NOISE_SUPPR      0x5c    /* noise suppression  */
  46 #define IRB_RX_POLARITY_INV     0x68    /* polarity inverter  */
  47 
  48 /*
  49  * IRQ set: Enable full FIFO                 1  -> bit  3;
  50  *          Enable overrun IRQ               1  -> bit  2;
  51  *          Enable last symbol IRQ           1  -> bit  1:
  52  *          Enable RX interrupt              1  -> bit  0;
  53  */
  54 #define IRB_RX_INTS             0x0f
  55 #define IRB_RX_OVERRUN_INT      0x04
  56  /* maximum symbol period (microsecs),timeout to detect end of symbol train */
  57 #define MAX_SYMB_TIME           0x5000
  58 #define IRB_SAMPLE_FREQ         10000000
  59 #define IRB_FIFO_NOT_EMPTY      0xff00
  60 #define IRB_OVERFLOW            0x4
  61 #define IRB_TIMEOUT             0xffff
  62 #define IR_ST_NAME "st-rc"
  63 
  64 static void st_rc_send_lirc_timeout(struct rc_dev *rdev)
  65 {
  66         struct ir_raw_event ev = { .timeout = true, .duration = rdev->timeout };
  67         ir_raw_event_store(rdev, &ev);
  68 }
  69 
  70 /*
  71  * RX graphical example to better understand the difference between ST IR block
  72  * output and standard definition used by LIRC (and most of the world!)
  73  *
  74  *           mark                                     mark
  75  *      |-IRB_RX_ON-|                            |-IRB_RX_ON-|
  76  *      ___  ___  ___                            ___  ___  ___             _
  77  *      | |  | |  | |                            | |  | |  | |             |
  78  *      | |  | |  | |         space 0            | |  | |  | |   space 1   |
  79  * _____| |__| |__| |____________________________| |__| |__| |_____________|
  80  *
  81  *      |--------------- IRB_RX_SYS -------------|------ IRB_RX_SYS -------|
  82  *
  83  *      |------------- encoding bit 0 -----------|---- encoding bit 1 -----|
  84  *
  85  * ST hardware returns mark (IRB_RX_ON) and total symbol time (IRB_RX_SYS), so
  86  * convert to standard mark/space we have to calculate space=(IRB_RX_SYS-mark)
  87  * The mark time represents the amount of time the carrier (usually 36-40kHz)
  88  * is detected.The above examples shows Pulse Width Modulation encoding where
  89  * bit 0 is represented by space>mark.
  90  */
  91 
  92 static irqreturn_t st_rc_rx_interrupt(int irq, void *data)
  93 {
  94         unsigned long timeout;
  95         unsigned int symbol, mark = 0;
  96         struct st_rc_device *dev = data;
  97         int last_symbol = 0;
  98         u32 status, int_status;
  99         struct ir_raw_event ev = {};
 100 
 101         if (dev->irq_wake)
 102                 pm_wakeup_event(dev->dev, 0);
 103 
 104         /* FIXME: is 10ms good enough ? */
 105         timeout = jiffies +  msecs_to_jiffies(10);
 106         do {
 107                 status  = readl(dev->rx_base + IRB_RX_STATUS);
 108                 if (!(status & (IRB_FIFO_NOT_EMPTY | IRB_OVERFLOW)))
 109                         break;
 110 
 111                 int_status = readl(dev->rx_base + IRB_RX_INT_STATUS);
 112                 if (unlikely(int_status & IRB_RX_OVERRUN_INT)) {
 113                         /* discard the entire collection in case of errors!  */
 114                         ir_raw_event_reset(dev->rdev);
 115                         dev_info(dev->dev, "IR RX overrun\n");
 116                         writel(IRB_RX_OVERRUN_INT,
 117                                         dev->rx_base + IRB_RX_INT_CLEAR);
 118                         continue;
 119                 }
 120 
 121                 symbol = readl(dev->rx_base + IRB_RX_SYS);
 122                 mark = readl(dev->rx_base + IRB_RX_ON);
 123 
 124                 if (symbol == IRB_TIMEOUT)
 125                         last_symbol = 1;
 126 
 127                  /* Ignore any noise */
 128                 if ((mark > 2) && (symbol > 1)) {
 129                         symbol -= mark;
 130                         if (dev->overclocking) { /* adjustments to timings */
 131                                 symbol *= dev->sample_mult;
 132                                 symbol /= dev->sample_div;
 133                                 mark *= dev->sample_mult;
 134                                 mark /= dev->sample_div;
 135                         }
 136 
 137                         ev.duration = US_TO_NS(mark);
 138                         ev.pulse = true;
 139                         ir_raw_event_store(dev->rdev, &ev);
 140 
 141                         if (!last_symbol) {
 142                                 ev.duration = US_TO_NS(symbol);
 143                                 ev.pulse = false;
 144                                 ir_raw_event_store(dev->rdev, &ev);
 145                         } else  {
 146                                 st_rc_send_lirc_timeout(dev->rdev);
 147                         }
 148 
 149                 }
 150                 last_symbol = 0;
 151         } while (time_is_after_jiffies(timeout));
 152 
 153         writel(IRB_RX_INTS, dev->rx_base + IRB_RX_INT_CLEAR);
 154 
 155         /* Empty software fifo */
 156         ir_raw_event_handle(dev->rdev);
 157         return IRQ_HANDLED;
 158 }
 159 
 160 static void st_rc_hardware_init(struct st_rc_device *dev)
 161 {
 162         int baseclock, freqdiff;
 163         unsigned int rx_max_symbol_per = MAX_SYMB_TIME;
 164         unsigned int rx_sampling_freq_div;
 165 
 166         /* Enable the IP */
 167         reset_control_deassert(dev->rstc);
 168 
 169         clk_prepare_enable(dev->sys_clock);
 170         baseclock = clk_get_rate(dev->sys_clock);
 171 
 172         /* IRB input pins are inverted internally from high to low. */
 173         writel(1, dev->rx_base + IRB_RX_POLARITY_INV);
 174 
 175         rx_sampling_freq_div = baseclock / IRB_SAMPLE_FREQ;
 176         writel(rx_sampling_freq_div, dev->base + IRB_SAMPLE_RATE_COMM);
 177 
 178         freqdiff = baseclock - (rx_sampling_freq_div * IRB_SAMPLE_FREQ);
 179         if (freqdiff) { /* over clocking, workout the adjustment factors */
 180                 dev->overclocking = true;
 181                 dev->sample_mult = 1000;
 182                 dev->sample_div = baseclock / (10000 * rx_sampling_freq_div);
 183                 rx_max_symbol_per = (rx_max_symbol_per * 1000)/dev->sample_div;
 184         }
 185 
 186         writel(rx_max_symbol_per, dev->rx_base + IRB_MAX_SYM_PERIOD);
 187 }
 188 
 189 static int st_rc_remove(struct platform_device *pdev)
 190 {
 191         struct st_rc_device *rc_dev = platform_get_drvdata(pdev);
 192 
 193         dev_pm_clear_wake_irq(&pdev->dev);
 194         device_init_wakeup(&pdev->dev, false);
 195         clk_disable_unprepare(rc_dev->sys_clock);
 196         rc_unregister_device(rc_dev->rdev);
 197         return 0;
 198 }
 199 
 200 static int st_rc_open(struct rc_dev *rdev)
 201 {
 202         struct st_rc_device *dev = rdev->priv;
 203         unsigned long flags;
 204         local_irq_save(flags);
 205         /* enable interrupts and receiver */
 206         writel(IRB_RX_INTS, dev->rx_base + IRB_RX_INT_EN);
 207         writel(0x01, dev->rx_base + IRB_RX_EN);
 208         local_irq_restore(flags);
 209 
 210         return 0;
 211 }
 212 
 213 static void st_rc_close(struct rc_dev *rdev)
 214 {
 215         struct st_rc_device *dev = rdev->priv;
 216         /* disable interrupts and receiver */
 217         writel(0x00, dev->rx_base + IRB_RX_EN);
 218         writel(0x00, dev->rx_base + IRB_RX_INT_EN);
 219 }
 220 
 221 static int st_rc_probe(struct platform_device *pdev)
 222 {
 223         int ret = -EINVAL;
 224         struct rc_dev *rdev;
 225         struct device *dev = &pdev->dev;
 226         struct resource *res;
 227         struct st_rc_device *rc_dev;
 228         struct device_node *np = pdev->dev.of_node;
 229         const char *rx_mode;
 230 
 231         rc_dev = devm_kzalloc(dev, sizeof(struct st_rc_device), GFP_KERNEL);
 232 
 233         if (!rc_dev)
 234                 return -ENOMEM;
 235 
 236         rdev = rc_allocate_device(RC_DRIVER_IR_RAW);
 237 
 238         if (!rdev)
 239                 return -ENOMEM;
 240 
 241         if (np && !of_property_read_string(np, "rx-mode", &rx_mode)) {
 242 
 243                 if (!strcmp(rx_mode, "uhf")) {
 244                         rc_dev->rxuhfmode = true;
 245                 } else if (!strcmp(rx_mode, "infrared")) {
 246                         rc_dev->rxuhfmode = false;
 247                 } else {
 248                         dev_err(dev, "Unsupported rx mode [%s]\n", rx_mode);
 249                         goto err;
 250                 }
 251 
 252         } else {
 253                 goto err;
 254         }
 255 
 256         rc_dev->sys_clock = devm_clk_get(dev, NULL);
 257         if (IS_ERR(rc_dev->sys_clock)) {
 258                 dev_err(dev, "System clock not found\n");
 259                 ret = PTR_ERR(rc_dev->sys_clock);
 260                 goto err;
 261         }
 262 
 263         rc_dev->irq = platform_get_irq(pdev, 0);
 264         if (rc_dev->irq < 0) {
 265                 ret = rc_dev->irq;
 266                 goto err;
 267         }
 268 
 269         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 270 
 271         rc_dev->base = devm_ioremap_resource(dev, res);
 272         if (IS_ERR(rc_dev->base)) {
 273                 ret = PTR_ERR(rc_dev->base);
 274                 goto err;
 275         }
 276 
 277         if (rc_dev->rxuhfmode)
 278                 rc_dev->rx_base = rc_dev->base + 0x40;
 279         else
 280                 rc_dev->rx_base = rc_dev->base;
 281 
 282         rc_dev->rstc = reset_control_get_optional_exclusive(dev, NULL);
 283         if (IS_ERR(rc_dev->rstc)) {
 284                 ret = PTR_ERR(rc_dev->rstc);
 285                 goto err;
 286         }
 287 
 288         rc_dev->dev = dev;
 289         platform_set_drvdata(pdev, rc_dev);
 290         st_rc_hardware_init(rc_dev);
 291 
 292         rdev->allowed_protocols = RC_PROTO_BIT_ALL_IR_DECODER;
 293         /* rx sampling rate is 10Mhz */
 294         rdev->rx_resolution = 100;
 295         rdev->timeout = US_TO_NS(MAX_SYMB_TIME);
 296         rdev->priv = rc_dev;
 297         rdev->open = st_rc_open;
 298         rdev->close = st_rc_close;
 299         rdev->driver_name = IR_ST_NAME;
 300         rdev->map_name = RC_MAP_EMPTY;
 301         rdev->device_name = "ST Remote Control Receiver";
 302 
 303         ret = rc_register_device(rdev);
 304         if (ret < 0)
 305                 goto clkerr;
 306 
 307         rc_dev->rdev = rdev;
 308         if (devm_request_irq(dev, rc_dev->irq, st_rc_rx_interrupt,
 309                              0, IR_ST_NAME, rc_dev) < 0) {
 310                 dev_err(dev, "IRQ %d register failed\n", rc_dev->irq);
 311                 ret = -EINVAL;
 312                 goto rcerr;
 313         }
 314 
 315         /* enable wake via this device */
 316         device_init_wakeup(dev, true);
 317         dev_pm_set_wake_irq(dev, rc_dev->irq);
 318 
 319         /*
 320          * for LIRC_MODE_MODE2 or LIRC_MODE_PULSE or LIRC_MODE_RAW
 321          * lircd expects a long space first before a signal train to sync.
 322          */
 323         st_rc_send_lirc_timeout(rdev);
 324 
 325         dev_info(dev, "setup in %s mode\n", rc_dev->rxuhfmode ? "UHF" : "IR");
 326 
 327         return ret;
 328 rcerr:
 329         rc_unregister_device(rdev);
 330         rdev = NULL;
 331 clkerr:
 332         clk_disable_unprepare(rc_dev->sys_clock);
 333 err:
 334         rc_free_device(rdev);
 335         dev_err(dev, "Unable to register device (%d)\n", ret);
 336         return ret;
 337 }
 338 
 339 #ifdef CONFIG_PM_SLEEP
 340 static int st_rc_suspend(struct device *dev)
 341 {
 342         struct st_rc_device *rc_dev = dev_get_drvdata(dev);
 343 
 344         if (device_may_wakeup(dev)) {
 345                 if (!enable_irq_wake(rc_dev->irq))
 346                         rc_dev->irq_wake = 1;
 347                 else
 348                         return -EINVAL;
 349         } else {
 350                 pinctrl_pm_select_sleep_state(dev);
 351                 writel(0x00, rc_dev->rx_base + IRB_RX_EN);
 352                 writel(0x00, rc_dev->rx_base + IRB_RX_INT_EN);
 353                 clk_disable_unprepare(rc_dev->sys_clock);
 354                 reset_control_assert(rc_dev->rstc);
 355         }
 356 
 357         return 0;
 358 }
 359 
 360 static int st_rc_resume(struct device *dev)
 361 {
 362         struct st_rc_device *rc_dev = dev_get_drvdata(dev);
 363         struct rc_dev   *rdev = rc_dev->rdev;
 364 
 365         if (rc_dev->irq_wake) {
 366                 disable_irq_wake(rc_dev->irq);
 367                 rc_dev->irq_wake = 0;
 368         } else {
 369                 pinctrl_pm_select_default_state(dev);
 370                 st_rc_hardware_init(rc_dev);
 371                 if (rdev->users) {
 372                         writel(IRB_RX_INTS, rc_dev->rx_base + IRB_RX_INT_EN);
 373                         writel(0x01, rc_dev->rx_base + IRB_RX_EN);
 374                 }
 375         }
 376 
 377         return 0;
 378 }
 379 
 380 #endif
 381 
 382 static SIMPLE_DEV_PM_OPS(st_rc_pm_ops, st_rc_suspend, st_rc_resume);
 383 
 384 #ifdef CONFIG_OF
 385 static const struct of_device_id st_rc_match[] = {
 386         { .compatible = "st,comms-irb", },
 387         {},
 388 };
 389 
 390 MODULE_DEVICE_TABLE(of, st_rc_match);
 391 #endif
 392 
 393 static struct platform_driver st_rc_driver = {
 394         .driver = {
 395                 .name = IR_ST_NAME,
 396                 .of_match_table = of_match_ptr(st_rc_match),
 397                 .pm     = &st_rc_pm_ops,
 398         },
 399         .probe = st_rc_probe,
 400         .remove = st_rc_remove,
 401 };
 402 
 403 module_platform_driver(st_rc_driver);
 404 
 405 MODULE_DESCRIPTION("RC Transceiver driver for STMicroelectronics platforms");
 406 MODULE_AUTHOR("STMicroelectronics (R&D) Ltd");
 407 MODULE_LICENSE("GPL");

/* [<][>][^][v][top][bottom][index][help] */