1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "backlight.h"
6#include <ddk/debug.h>
7#include <ddk/protocol/platform-device.h>
8
9namespace astro_display {
10
11// Table from Linux source
12// TODO(ZX-2455): Need to separate backlight driver from display driver
13struct I2cCommand {
14    uint8_t reg;
15    uint8_t val;
16};
17
18namespace {
19constexpr I2cCommand kBacklightInitTable[] = {
20    {0xa2, 0x20},
21    {0xa5, 0x54},
22    {0x00, 0xff},
23    {0x01, 0x05},
24    {0xa2, 0x20},
25    {0xa5, 0x54},
26    {0xa1, 0xb7},
27    {0xa0, 0xff},
28    {0x00, 0x80},
29};
30} // namespace
31
32zx_status_t Backlight::Init(zx_device_t* parent) {
33    if (initialized_) {
34        return ZX_OK;
35    }
36
37    platform_device_protocol_t pdev;
38    zx_status_t status = device_get_protocol(parent, ZX_PROTOCOL_PLATFORM_DEV, &pdev);
39    if (status != ZX_OK) {
40        DISP_ERROR("Could not obtain platform device protocol\n");
41        return status;
42    }
43
44    // Obtain I2C Protocol for backlight
45    status = device_get_protocol(parent, ZX_PROTOCOL_I2C, &i2c_);
46    if (status != ZX_OK) {
47        DISP_ERROR("Could not obtain I2C protocol\n");
48        return status;
49    }
50
51    // Obtain GPIO Protocol for backlight enable
52    status = pdev_get_protocol(&pdev, ZX_PROTOCOL_GPIO, GPIO_BL, &gpio_);
53    if (status != ZX_OK) {
54        DISP_ERROR("Could not obtain GPIO protocol\n");
55        return status;
56    }
57
58    // set gpio pin as output
59    gpio_config_out(&gpio_, 1);
60    zx_nanosleep(zx_deadline_after(ZX_USEC(10))); // optional small delay for pin to settle
61    initialized_ = true;
62    return ZX_OK;
63}
64
65void Backlight::Enable() {
66    ZX_DEBUG_ASSERT(initialized_);
67    if (enabled_) {
68        return;
69    }
70    // power on backlight
71    gpio_write(&gpio_, 1);
72    zx_nanosleep(zx_deadline_after(ZX_MSEC(1))); // delay to ensure backlight is powered on
73
74    for (size_t i = 0; i < fbl::count_of(kBacklightInitTable); i++) {
75        if (i2c_write_sync(&i2c_, &kBacklightInitTable[i], 2) != ZX_OK) {
76            DISP_ERROR("Backlight write failed: reg[0x%x]: 0x%x\n", kBacklightInitTable[i].reg,
77                       kBacklightInitTable[i].val);
78        }
79    }
80    enabled_ = true;
81    return;
82}
83
84void Backlight::Disable() {
85    ZX_DEBUG_ASSERT(initialized_);
86    if (!enabled_) {
87        return;
88    }
89    // power off backlight
90    gpio_write(&gpio_, 0);
91    enabled_ = false;
92}
93
94} // namespace astro_display
95