mirror of
https://github.com/torvalds/linux.git
synced 2024-12-30 14:52:05 +00:00
621da7d93c
Some of the newer MDP5 versions support Source Split of SSPPs. It is a feature that allows us to route the output of a hwpipe to 2 Layer Mixers. This is required to achieve the following use cases: - Dual DSI: For high res DSI panels (such as 2560x1600 etc), a single DSI interface doesn't have the bandwidth to drive the required pixel clock. We use 2 DSI interfaces to drive the left and right halves of the panel (i.e, 1280x1600 each). The MDP5 pipeline here would look like: LM0 -- DSPP0 -- INTF1 -- DSI1 / hwpipe-- \ LM1 -- DSPP1 -- INTF2 -- DSI2 A single hwpipe is used to scan out the left and right halves to DSI1 and DSI2 respectively. In order to do this, we need to configure the 2 Layer Mixers in Source Split mode. - HDMI 4K: In order to support resolutions with width higher than the max width supported by a hwpipe, we club 2 hwpipes together: hwpipe1 --- LM0 -- DSPP0 - - \ - -- 3D Mux -- INTF0 -- HDMI - - / hwpipe2 --- LM1 -- DSPP1 hwpipe1 is staged on the 'left' Layer Mixer, and hwpipe2 is staged on the 'right' Layer Mixer. An additional block called the '3D Mux' is used to merge the output of the 2 DSPPs to a single interface. In this use case, it is possible that a 4K surface is downscaled and placed completely within one of the halves. In order to support such scenarios (and keep the programming simple), Layer Mixers with Source Split can be assigned 2 hw pipes per stage. While scanning out, the HW takes care of fetching the pixels fom the correct pipe. Add a MDP cap to tell whether the HW supports source split or not. Add a MDP LM cap that tells whether a LM instance can operate in source split mode (and generate the 'left' part of the display output). Signed-off-by: Archit Taneja <architt@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
149 lines
4.2 KiB
C
149 lines
4.2 KiB
C
/*
|
|
* Copyright (C) 2013 Red Hat
|
|
* Author: Rob Clark <robdclark@gmail.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License version 2 as published by
|
|
* the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
* more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License along with
|
|
* this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#ifndef __MDP_KMS_H__
|
|
#define __MDP_KMS_H__
|
|
|
|
#include <linux/clk.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/regulator/consumer.h>
|
|
|
|
#include "msm_drv.h"
|
|
#include "msm_kms.h"
|
|
#include "mdp_common.xml.h"
|
|
|
|
struct mdp_kms;
|
|
|
|
struct mdp_kms_funcs {
|
|
struct msm_kms_funcs base;
|
|
void (*set_irqmask)(struct mdp_kms *mdp_kms, uint32_t irqmask,
|
|
uint32_t old_irqmask);
|
|
};
|
|
|
|
struct mdp_kms {
|
|
struct msm_kms base;
|
|
|
|
const struct mdp_kms_funcs *funcs;
|
|
|
|
/* irq handling: */
|
|
bool in_irq;
|
|
struct list_head irq_list; /* list of mdp4_irq */
|
|
uint32_t vblank_mask; /* irq bits set for userspace vblank */
|
|
uint32_t cur_irq_mask; /* current irq mask */
|
|
};
|
|
#define to_mdp_kms(x) container_of(x, struct mdp_kms, base)
|
|
|
|
static inline void mdp_kms_init(struct mdp_kms *mdp_kms,
|
|
const struct mdp_kms_funcs *funcs)
|
|
{
|
|
mdp_kms->funcs = funcs;
|
|
INIT_LIST_HEAD(&mdp_kms->irq_list);
|
|
msm_kms_init(&mdp_kms->base, &funcs->base);
|
|
}
|
|
|
|
/*
|
|
* irq helpers:
|
|
*/
|
|
|
|
/* For transiently registering for different MDP irqs that various parts
|
|
* of the KMS code need during setup/configuration. These are not
|
|
* necessarily the same as what drm_vblank_get/put() are requesting, and
|
|
* the hysteresis in drm_vblank_put() is not necessarily desirable for
|
|
* internal housekeeping related irq usage.
|
|
*/
|
|
struct mdp_irq {
|
|
struct list_head node;
|
|
uint32_t irqmask;
|
|
bool registered;
|
|
void (*irq)(struct mdp_irq *irq, uint32_t irqstatus);
|
|
};
|
|
|
|
void mdp_dispatch_irqs(struct mdp_kms *mdp_kms, uint32_t status);
|
|
void mdp_update_vblank_mask(struct mdp_kms *mdp_kms, uint32_t mask, bool enable);
|
|
void mdp_irq_wait(struct mdp_kms *mdp_kms, uint32_t irqmask);
|
|
void mdp_irq_register(struct mdp_kms *mdp_kms, struct mdp_irq *irq);
|
|
void mdp_irq_unregister(struct mdp_kms *mdp_kms, struct mdp_irq *irq);
|
|
void mdp_irq_update(struct mdp_kms *mdp_kms);
|
|
|
|
/*
|
|
* pixel format helpers:
|
|
*/
|
|
|
|
struct mdp_format {
|
|
struct msm_format base;
|
|
enum mdp_bpc bpc_r, bpc_g, bpc_b;
|
|
enum mdp_bpc_alpha bpc_a;
|
|
uint8_t unpack[4];
|
|
bool alpha_enable, unpack_tight;
|
|
uint8_t cpp, unpack_count;
|
|
enum mdp_fetch_type fetch_type;
|
|
enum mdp_chroma_samp_type chroma_sample;
|
|
bool is_yuv;
|
|
};
|
|
#define to_mdp_format(x) container_of(x, struct mdp_format, base)
|
|
#define MDP_FORMAT_IS_YUV(mdp_format) ((mdp_format)->is_yuv)
|
|
|
|
uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats, bool rgb_only);
|
|
const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format);
|
|
|
|
/* MDP capabilities */
|
|
#define MDP_CAP_SMP BIT(0) /* Shared Memory Pool */
|
|
#define MDP_CAP_DSC BIT(1) /* VESA Display Stream Compression */
|
|
#define MDP_CAP_CDM BIT(2) /* Chroma Down Module (HDMI 2.0 YUV) */
|
|
#define MDP_CAP_SRC_SPLIT BIT(3) /* Source Split of SSPPs */
|
|
|
|
/* MDP pipe capabilities */
|
|
#define MDP_PIPE_CAP_HFLIP BIT(0)
|
|
#define MDP_PIPE_CAP_VFLIP BIT(1)
|
|
#define MDP_PIPE_CAP_SCALE BIT(2)
|
|
#define MDP_PIPE_CAP_CSC BIT(3)
|
|
#define MDP_PIPE_CAP_DECIMATION BIT(4)
|
|
#define MDP_PIPE_CAP_SW_PIX_EXT BIT(5)
|
|
#define MDP_PIPE_CAP_CURSOR BIT(6)
|
|
|
|
/* MDP layer mixer caps */
|
|
#define MDP_LM_CAP_DISPLAY BIT(0)
|
|
#define MDP_LM_CAP_WB BIT(1)
|
|
#define MDP_LM_CAP_PAIR BIT(2)
|
|
|
|
static inline bool pipe_supports_yuv(uint32_t pipe_caps)
|
|
{
|
|
return (pipe_caps & MDP_PIPE_CAP_SCALE) &&
|
|
(pipe_caps & MDP_PIPE_CAP_CSC);
|
|
}
|
|
|
|
enum csc_type {
|
|
CSC_RGB2RGB = 0,
|
|
CSC_YUV2RGB,
|
|
CSC_RGB2YUV,
|
|
CSC_YUV2YUV,
|
|
CSC_MAX
|
|
};
|
|
|
|
struct csc_cfg {
|
|
enum csc_type type;
|
|
uint32_t matrix[9];
|
|
uint32_t pre_bias[3];
|
|
uint32_t post_bias[3];
|
|
uint32_t pre_clamp[6];
|
|
uint32_t post_clamp[6];
|
|
};
|
|
|
|
struct csc_cfg *mdp_get_default_csc_cfg(enum csc_type);
|
|
|
|
#endif /* __MDP_KMS_H__ */
|