blob: 3ceb2b3c110a0de81d134836c30040c26ef0925b [file] [log] [blame]
/*
* Copyright (c) 2014 - 2015, The Linux Foundation. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright notice, this list of
* conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided
* with the distribution.
* * Neither the name of The Linux Foundation nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef __HW_FRAMEBUFFER_H__
#define __HW_FRAMEBUFFER_H__
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <linux/msm_mdp_ext.h>
#include <video/msm_hdmi_modes.h>
#include <linux/mdss_rotator.h>
#include <poll.h>
#include <pthread.h>
#include "hw_interface.h"
namespace sde {
class HWFrameBuffer : public HWInterface {
public:
explicit HWFrameBuffer(BufferSyncHandler *buffer_sync_handler);
DisplayError Init();
DisplayError Deinit();
virtual DisplayError GetHWCapabilities(HWResourceInfo *hw_res_info);
virtual DisplayError Open(HWDeviceType type, Handle *device, HWEventHandler *eventhandler);
virtual DisplayError Close(Handle device);
virtual DisplayError GetNumDisplayAttributes(Handle device, uint32_t *count);
virtual DisplayError GetDisplayAttributes(Handle device, HWDisplayAttributes *display_attributes,
uint32_t index);
virtual DisplayError SetDisplayAttributes(Handle device, uint32_t index);
virtual DisplayError GetConfigIndex(Handle device, uint32_t mode, uint32_t *index);
virtual DisplayError PowerOn(Handle device);
virtual DisplayError PowerOff(Handle device);
virtual DisplayError Doze(Handle device);
virtual DisplayError SetVSyncState(Handle device, bool enable);
virtual DisplayError Standby(Handle device);
virtual DisplayError OpenRotatorSession(Handle device, HWRotateInfo *rotate_info);
virtual DisplayError CloseRotatorSession(Handle device, int32_t session_id);
virtual DisplayError Validate(Handle device, HWLayers *hw_layers);
virtual DisplayError Commit(Handle device, HWLayers *hw_layers);
virtual DisplayError Flush(Handle device);
virtual void SetIdleTimeoutMs(Handle device, uint32_t timeout_ms);
private:
struct HWDisplay {
mdp_layer_commit mdp_disp_commit;
mdp_input_layer mdp_in_layers[kMaxSDELayers * 2]; // split panel (left + right)
mdp_scale_data scale_data[kMaxSDELayers * 2];
mdp_output_layer mdp_out_layer;
HWDisplay() { Reset(); }
void Reset() {
memset(&mdp_disp_commit, 0, sizeof(mdp_disp_commit));
memset(&mdp_in_layers, 0, sizeof(mdp_in_layers));
memset(&mdp_out_layer, 0, sizeof(mdp_out_layer));
memset(&scale_data, 0, sizeof(scale_data));
for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
mdp_in_layers[i].buffer.fence = -1;
}
mdp_disp_commit.version = MDP_COMMIT_VERSION_1_0;
mdp_disp_commit.commit_v1.input_layers = mdp_in_layers;
mdp_disp_commit.commit_v1.output_layer = &mdp_out_layer;
mdp_disp_commit.commit_v1.release_fence = -1;
mdp_disp_commit.commit_v1.retire_fence = -1;
}
mdp_scale_data* GetScaleDataRef(uint32_t index) { return &scale_data[index]; }
};
struct HWRotator {
struct mdp_rotation_request mdp_rot_req;
struct mdp_rotation_item mdp_rot_layers[kMaxSDELayers * 2]; // split panel (left + right)
HWRotator() { Reset(); }
void Reset() {
memset(&mdp_rot_req, 0, sizeof(mdp_rot_req));
memset(&mdp_rot_layers, 0, sizeof(mdp_rot_layers));
for (uint32_t i = 0; i < kMaxSDELayers * 2; i++) {
mdp_rot_layers[i].input.fence = -1;
mdp_rot_layers[i].output.fence = -1;
}
mdp_rot_req.version = MDP_ROTATION_REQUEST_VERSION_1_0;
mdp_rot_req.list = mdp_rot_layers;
}
};
struct HWContext {
HWDeviceType type;
int device_fd;
HWRotator hw_rotator;
HWDisplay hw_display;
HWContext() : type(kDeviceMax), device_fd(-1) { }
};
enum PanelType {
kNoPanel,
kCommandModePanel,
kVideoModePanel,
kDTvPanel,
kWriteBackPanel,
kLVDSPanel,
kEDPPanel,
};
enum {
kHWEventVSync,
kHWEventBlank,
};
// Maps to the msm_fb_panel_info
struct PanelInfo {
PanelType type; // Smart or Dumb
bool partial_update; // Partial update feature
int left_align; // ROI left alignment restriction
int width_align; // ROI width alignment restriction
int top_align;; // ROI top alignment restriction
int height_align; // ROI height alignment restriction
int min_roi_width; // Min width needed for ROI
int min_roi_height; // Min height needed for ROI
bool needs_roi_merge; // Merge ROI's of both the DSI's
bool dynamic_fps; // Panel Supports dynamic fps
uint32_t min_fps; // Min fps supported by panel
uint32_t max_fps; // Max fps supported by panel
PanelInfo() : type(kNoPanel), partial_update(false), left_align(false), width_align(false),
top_align(false), height_align(false), min_roi_width(0), min_roi_height(0),
needs_roi_merge(false), dynamic_fps(false), min_fps(0), max_fps(0) { }
};
static const int kMaxStringLength = 1024;
static const int kNumPhysicalDisplays = 2;
static const int kNumDisplayEvents = 3;
static const int kHWMdssVersion5 = 500; // MDSS_V5
DisplayError DisplayValidate(HWContext *device_ctx, HWLayers *hw_layers);
DisplayError DisplayCommit(HWContext *device_ctx, HWLayers *hw_layers);
void SetRotatorCtrlParams(HWContext *device_ctx, HWLayers *hw_layers);
void SetRotatorBufferParams(HWContext *device_ctx, HWLayers *hw_layers);
DisplayError RotatorValidate(HWContext *device_ctx, HWLayers *hw_layers);
DisplayError RotatorCommit(HWContext *device_ctx, HWLayers *hw_layers);
inline DisplayError SetFormat(const LayerBufferFormat &source, uint32_t *target);
inline DisplayError SetStride(HWDeviceType device_type, LayerBufferFormat format,
uint32_t width, uint32_t *target);
inline void SetBlending(const LayerBlending &source, mdss_mdp_blend_op *target);
inline void SetRect(const LayerRect &source, mdp_rect *target);
inline void SyncMerge(const int &fd1, const int &fd2, int *target);
inline const char *GetDeviceString(HWDeviceType type);
// Event Thread to receive vsync/blank events
static void* DisplayEventThread(void *context);
void* DisplayEventThreadHandler();
void HandleVSync(int display_id, char *data);
void HandleBlank(int display_id, char *data);
void HandleIdleTimeout(int display_id, char *data);
// Populates HW FrameBuffer Node Index
void PopulateFBNodeIndex();
// Populates the Panel Info based on node index
void PopulatePanelInfo(int fb_index);
// Populates HW Capabilities
DisplayError PopulateHWCapabilities();
int ParseLine(char *input, char *token[], const uint32_t max_token, uint32_t *count);
// HDMI Related Functions
bool EnableHotPlugDetection(int enable);
int GetHDMIModeCount();
bool MapHDMIDisplayTiming(const msm_hdmi_mode_timing_info *mode, fb_var_screeninfo *info);
// Pointers to system calls which are either mapped to actual system call or virtual driver.
int (*ioctl_)(int, int, ...);
int (*open_)(const char *, int, ...);
int (*close_)(int);
int (*poll_)(struct pollfd *, nfds_t, int);
ssize_t (*pread_)(int, void *, size_t, off_t);
ssize_t (*pwrite_)(int, const void *, size_t, off_t);
FILE* (*fopen_)( const char *fname, const char *mode);
int (*fclose_)(FILE* fileptr);
ssize_t (*getline_)(char **lineptr, size_t *linelen, FILE *stream);
// Store the Device EventHandlers - used for callback
HWEventHandler *event_handler_[kNumPhysicalDisplays];
pollfd poll_fds_[kNumPhysicalDisplays][kNumDisplayEvents];
pthread_t event_thread_;
const char *event_thread_name_;
bool fake_vsync_;
bool exit_threads_;
HWResourceInfo hw_resource_;
int fb_node_index_[kDeviceMax];
const char* fb_path_;
PanelInfo primary_panel_info_;
bool hotplug_enabled_;
uint32_t hdmi_mode_count_;
uint32_t hdmi_modes_[256];
// Holds the hdmi timing information. Ex: resolution, fps etc.,
msm_hdmi_mode_timing_info *supported_video_modes_;
BufferSyncHandler *buffer_sync_handler_;
};
} // namespace sde
#endif // __HW_FRAMEBUFFER_H__