Landfall

Annotated pkg/devices/backlight/src/spi-qi_lb60/backlight-spi-qi_lb60.cc

0:89a1bc19c1fc
2018-05-13 Paul Boddie Added device libraries and programs, configuration files and examples. Also added an installation script and copyright and licensing information.
paul@0 1
/*
paul@0 2
 * Access a SPI server to update a display panel backlight.
paul@0 3
 * This server is specific to the Ben NanoNote.
paul@0 4
 *
paul@0 5
 * (c) 2018 Paul Boddie <paul@boddie.org.uk>
paul@0 6
 *
paul@0 7
 * This program is free software; you can redistribute it and/or
paul@0 8
 * modify it under the terms of the GNU General Public License as
paul@0 9
 * published by the Free Software Foundation; either version 2 of
paul@0 10
 * the License, or (at your option) any later version.
paul@0 11
 *
paul@0 12
 * This program is distributed in the hope that it will be useful,
paul@0 13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
paul@0 14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
paul@0 15
 * GNU General Public License for more details.
paul@0 16
 *
paul@0 17
 * You should have received a copy of the GNU General Public License
paul@0 18
 * along with this program; if not, write to the Free Software
paul@0 19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
paul@0 20
 * Boston, MA  02110-1301, USA
paul@0 21
 */
paul@0 22
paul@0 23
#include <l4/cxx/ipc_server>
paul@0 24
#include <l4/re/env>
paul@0 25
#include <l4/re/util/object_registry>
paul@0 26
#include <l4/sys/capability>
paul@0 27
paul@0 28
#include <stdlib.h>
paul@0 29
paul@0 30
#include <l4/devices/spi-client.h>
paul@0 31
#include "backlight-ops.h"
paul@0 32
paul@0 33
/* SPI access abstractions. */
paul@0 34
paul@0 35
static L4::Cap<Spi_device_interface> spi_device;
paul@0 36
paul@0 37
paul@0 38
paul@0 39
/* Backlight device. */
paul@0 40
paul@0 41
class Backlight_device_server : public L4::Server_object_t<L4::Kobject>
paul@0 42
{
paul@0 43
  int _min = 55, _max = 90, _start = 70;
paul@0 44
paul@0 45
  void set_duty(int level)
paul@0 46
  {
paul@0 47
    level = level < _min ? _min : (level > _max ? _max : level);
paul@0 48
paul@0 49
    /* PWM_DUTY = R05h<5:3> = 5% increments from min to max */
paul@0 50
paul@0 51
    int duty = ((level - _min) / 5) << 3;
paul@0 52
paul@0 53
    spi_device->send(16, 0x0516 | duty); /* R05h: GRB=0 (reset); PWM_DUTY=duty; SHDB2=1, SHDB1=1 (power-related); STB=0 (standby) */
paul@0 54
    spi_device->send(16, 0x0546 | duty); /* R05h: GRB=1 (normal operation); ... */
paul@0 55
    spi_device->send(16, 0x078d);        /* R07h: HBLK=141 (horizontal blanking period from start of hsync pulse to data start) */
paul@0 56
    spi_device->send(16, 0x1301);        /* R13h: IN_SEL=1 (alignment mode) */
paul@0 57
    spi_device->send(16, 0x0547 | duty); /* R05h: ...; STB=1 (not standby) */
paul@0 58
  }
paul@0 59
paul@0 60
public:
paul@0 61
  /* Dispatch incoming requests. */
paul@0 62
paul@0 63
  int dispatch(l4_umword_t obj, L4::Ipc::Iostream &ios)
paul@0 64
  {
paul@0 65
    l4_msgtag_t tag;
paul@0 66
    int arg;
paul@0 67
paul@0 68
    (void) obj;
paul@0 69
    ios >> tag;
paul@0 70
paul@0 71
    switch (tag.label())
paul@0 72
    {
paul@0 73
      case Backlight_op_disable:
paul@0 74
        disable();
paul@0 75
        return L4_EOK;
paul@0 76
paul@0 77
      case Backlight_op_enable:
paul@0 78
        enable();
paul@0 79
        return L4_EOK;
paul@0 80
paul@0 81
      case Backlight_op_set_brightness:
paul@0 82
        ios >> arg;
paul@0 83
        set_brightness(arg);
paul@0 84
        return L4_EOK;
paul@0 85
paul@0 86
      default:
paul@0 87
        return -L4_EBADPROTO;
paul@0 88
    }
paul@0 89
  }
paul@0 90
paul@0 91
  void disable()
paul@0 92
  {
paul@0 93
    spi_device->send(16, 0x055e);
paul@0 94
  }
paul@0 95
paul@0 96
  void enable()
paul@0 97
  {
paul@0 98
    set_duty(_start);
paul@0 99
  }
paul@0 100
paul@0 101
  /* Use the SPI device to update the brightness level. */
paul@0 102
paul@0 103
  void set_brightness(int level)
paul@0 104
  {
paul@0 105
    level = level < _min ? _min : (level > _max ? _max : level);
paul@0 106
    spi_device->send(16, 0x0300 | level); /* R03h: brightness */
paul@0 107
  }
paul@0 108
};
paul@0 109
paul@0 110
static L4Re::Util::Registry_server<> server;
paul@0 111
paul@0 112
paul@0 113
paul@0 114
int main(void)
paul@0 115
{
paul@0 116
  /* Obtain a reference to the SPI device. */
paul@0 117
paul@0 118
  spi_device = L4Re::Env::env()->get_cap<Spi_device_interface>("spi");
paul@0 119
  if (!spi_device.is_valid()) return 1;
paul@0 120
paul@0 121
  /* Initialise and register a new server object. */
paul@0 122
paul@0 123
  Backlight_device_server server_obj;
paul@0 124
  server.registry()->register_obj(&server_obj, "backlight");
paul@0 125
paul@0 126
  /* Enter the IPC server loop. */
paul@0 127
paul@0 128
  server.loop();
paul@0 129
  return 0;
paul@0 130
}