1 // Copyright 2017 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 #pragma once
6 
7 #include <ddk/protocol/display/controller.h>
8 #include <ddktl/device.h>
9 #include <ddktl/mmio.h>
10 #include <region-alloc/region-alloc.h>
11 #include <lib/zx/vmo.h>
12 
13 #include "gtt.h"
14 #include "pipe.h"
15 #include "power.h"
16 #include "registers-ddi.h"
17 #include "registers-pipe.h"
18 #include "registers-transcoder.h"
19 
20 namespace i915 {
21 
22 class Controller;
23 class DisplayDevice;
24 
25 // Thread safe weak-ref to the DisplayDevice, because the backlight device
26 // lifecycle is managed by devmgr but the DisplayDevice lifecycle is managed
27 // by the display controller class.
28 typedef struct display_ref {
29     mtx_t mtx;
30     DisplayDevice* display_device __TA_GUARDED(mtx);
31 } display_ref_t;
32 
33 
34 class DisplayDevice {
35 public:
36     DisplayDevice(Controller* device, uint64_t id, registers::Ddi ddi);
37     virtual ~DisplayDevice();
38 
39     bool AttachPipe(Pipe* pipe);
40     void ApplyConfiguration(const display_config_t* config);
41 
42     // Query whether or not there is a display attached to this ddi. Does not
43     // actually do any initialization - that is done by Init.
44     virtual bool Query() = 0;
45     // Does display mode agnostic ddi initialization - subclasses implement InitDdi.
46     bool Init();
47     // Initializes the display backlight for an already initialized display.
48     void InitBacklight();
49     // Resumes the ddi after suspend.
50     bool Resume();
51     // Loads ddi state from the hardware at driver startup.
52     void LoadActiveMode();
53     // Method to allow the display device to handle hotplug events. Returns
54     // true if the device can handle the event without disconnecting. Otherwise
55     // the device will be removed.
HandleHotplug(bool long_pulse)56     virtual bool HandleHotplug(bool long_pulse) { return false; }
57 
id()58     uint64_t id() const { return id_; }
ddi()59     registers::Ddi ddi() const { return ddi_; }
controller()60     Controller* controller() { return controller_; }
61 
62     virtual uint32_t i2c_bus_id() const = 0;
63 
pipe()64     Pipe* pipe() const { return pipe_; }
65 
is_hdmi()66     bool is_hdmi() const { return is_hdmi_; }
set_is_hdmi(bool is_hdmi)67     void set_is_hdmi(bool is_hdmi) { is_hdmi_ = is_hdmi; }
68 
HasBacklight()69     virtual bool HasBacklight() { return false; }
SetBacklightState(bool power,uint8_t brightness)70     virtual void SetBacklightState(bool power, uint8_t brightness) {}
GetBacklightState(bool * power,uint8_t * brightness)71     virtual void GetBacklightState(bool* power, uint8_t* brightness) {}
72 
73     virtual bool CheckPixelRate(uint64_t pixel_rate) = 0;
74 protected:
75     // Attempts to initialize the ddi.
76     virtual bool InitDdi() = 0;
InitBacklightHw()77     virtual bool InitBacklightHw() { return false; }
78 
79     // Configures the hardware to display content at the given resolution.
80     virtual bool DdiModeset(const display_mode_t& mode,
81                             registers::Pipe pipe, registers::Trans trans) = 0;
82     virtual bool ComputeDpllState(uint32_t pixel_clock_10khz, struct dpll_state* config) = 0;
83     // Load the clock rate from hardware if it's necessary when changing the transcoder.
84     virtual uint32_t LoadClockRateForTranscoder(registers::Trans transcoder) = 0;
85 
86     // Attaching a pipe to a display or configuring a pipe after display mode change has
87     // 3 steps. The second step is generic pipe configuration, whereas PipeConfigPreamble
88     // and PipeConfigEpilogue are responsible for display-type-specific configuration that
89     // must be done before and after the generic configuration.
90     virtual bool PipeConfigPreamble(const display_mode_t& mode,
91                                     registers::Pipe pipe, registers::Trans trans) = 0;
92     virtual bool PipeConfigEpilogue(const display_mode_t& mode,
93                                     registers::Pipe pipe, registers::Trans trans) = 0;
94 
95     ddk::MmioBuffer* mmio_space() const;
96 
97 private:
98     bool CheckNeedsModeset(const display_mode_t* mode);
99 
100     // Borrowed reference to Controller instance
101     Controller* controller_;
102 
103     uint64_t id_;
104     registers::Ddi ddi_;
105 
106     Pipe* pipe_= nullptr;
107 
108     PowerWellRef ddi_power_;
109 
110     bool inited_ = false;
111     display_mode_t info_ = {};
112     bool is_hdmi_ = false;
113 
114     zx_device_t* backlight_device_ = nullptr;
115     display_ref_t* display_ref_ = nullptr;
116 };
117 
118 } // namespace i915
119