Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions drivers/gpu/drm/phytium/phytium_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,18 +348,25 @@ static void phytium_crtc_gamma_set(struct drm_crtc *crtc)
uint32_t active_line = 0, timeout = 500;
int i;

if (!state)
return;

if (state->gamma_lut) {
if (WARN((state->gamma_lut->length/sizeof(struct drm_color_lut) != GAMMA_INDEX_MAX),
"gamma size is not match\n"))
return;
lut = (struct drm_color_lut *)state->gamma_lut->data;
if (!lut)
return;

config = phytium_readl_reg(priv, group_offset, PHYTIUM_DC_FRAMEBUFFER_CONFIG);
if (config & FRAMEBUFFER_OUTPUT) {
struct drm_display_mode *mode = &state->adjusted_mode;
uint32_t frame_time;
uint32_t value_a, value_b;

if (!mode)
return;
frame_time = mode->crtc_vtotal * mode->crtc_htotal / mode->crtc_clock;
value_b = (frame_time - 2) * mode->crtc_vtotal;
local_irq_save(flags);
Expand Down
148 changes: 138 additions & 10 deletions drivers/gpu/drm/phytium/phytium_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "pe220x_dp.h"
#include "phytium_panel.h"
#include "phytium_reg.h"
#include "phytium_crtc.h"

static void phytium_dp_aux_init(struct phytium_dp_device *phytium_dp);
static void handle_plugged_change(struct phytium_dp_device *phytium_dp, bool plugged);
Expand Down Expand Up @@ -310,19 +311,25 @@ static int phytium_connector_add_common_modes(struct phytium_dp_device *phytium_

static int phytium_connector_get_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_dp_device *phytium_dp = connector_to_dp_device(connector);
struct edid *edid;
int ret = 0;

if (phytium_dp->is_edp)
if (phytium_dp->is_edp) {
edid = phytium_dp->edp_edid;
else
} else if (priv->info.bmc_mode) {
edid = drm_get_edid(connector, &phytium_dp->aux.ddc);
} else {
edid = phytium_dp->detect_edid;
}

if (edid && drm_edid_is_valid(edid)) {
drm_connector_update_edid_property(connector, edid);
ret = drm_add_edid_modes(connector, edid);
phytium_dp->has_audio = drm_detect_monitor_audio(edid);
if (priv->info.bmc_mode)
phytium_dp->has_audio = drm_detect_monitor_audio(edid);
phytium_get_native_mode(phytium_dp);
if (dc_fake_mode_enable)
ret += phytium_connector_add_common_modes(phytium_dp);
Expand All @@ -331,7 +338,7 @@ static int phytium_connector_get_modes(struct drm_connector *connector)
phytium_dp->has_audio = false;
}

if (!phytium_dp->is_edp)
if (priv->info.bmc_mode)
kfree(edid);

return ret;
Expand Down Expand Up @@ -1723,8 +1730,33 @@ static void phytium_dp_handle_test_request(struct phytium_dp_device *phytium_dp)

}

static void phytium_dp_unset_edid(struct drm_connector *connector)
{
struct phytium_dp_device *phytium_dp = connector_to_dp_device(connector);

kfree(phytium_dp->detect_edid);
phytium_dp->detect_edid = NULL;
phytium_dp->has_audio = false;
}

static enum drm_connector_status phytium_dp_set_edid(struct drm_connector *connector)
{
struct phytium_dp_device *phytium_dp = connector_to_dp_device(connector);

phytium_dp_unset_edid(connector);
phytium_dp->detect_edid = drm_get_edid(connector, &phytium_dp->aux.ddc);
if (!phytium_dp->detect_edid)
return connector_status_disconnected;

phytium_dp->has_audio = drm_detect_monitor_audio(phytium_dp->detect_edid);

return connector_status_connected;
}

static int phytium_dp_long_pulse(struct drm_connector *connector, bool hpd_raw_state)
{
struct drm_device *dev = connector->dev;
struct phytium_display_private *priv = dev->dev_private;
struct phytium_dp_device *phytium_dp = connector_to_dp_device(connector);
enum drm_connector_status status = connector->status;
bool video_enable = false;
Expand Down Expand Up @@ -1759,6 +1791,12 @@ static int phytium_dp_long_pulse(struct drm_connector *connector, bool hpd_raw_s
video_enable = phytium_dp_hw_video_is_enable(phytium_dp);
phytium_dp_start_link_train(phytium_dp);

if (!priv->info.bmc_mode) {
status = phytium_dp_set_edid(connector);
if (status == connector_status_disconnected)
goto out;
}

if (video_enable) {
mdelay(2);
phytium_dp_hw_enable_video(phytium_dp);
Expand Down Expand Up @@ -2177,6 +2215,99 @@ void phytium_dp_adjust_link_train_parameter(struct phytium_dp_device *phytium_dp
phytium_dp->link_rate, phytium_dp->link_lane_count);
}

static void
phytium_dp_modify_dc_hsync_time(struct phytium_dp_device *phytium_dp)
{
struct drm_device *dev = NULL;
struct phytium_display_private *priv = NULL;
struct drm_connector *connector = NULL;
struct drm_crtc *crtc = NULL;
struct phytium_crtc *phytium_crtc = NULL;
struct drm_display_mode temp_mode = phytium_dp->mode;
int phys_pipe = 0, back_porch = 0, lines_add = 0;
int config = 0, fifo_value = 0;
uint32_t group_offset;

dev = phytium_dp->dev;
if (!dev) {
DRM_INFO("%s: dev is null\n", __func__);
return;
}

priv = dev->dev_private;
if (!priv) {
DRM_INFO("%s: priv is null\n", __func__);
return;
}

connector = &phytium_dp->connector;
if (!connector) {
DRM_INFO("%s: connector is null\n", __func__);
return;
}

crtc = connector->state->crtc;
if (!crtc)
return;

group_offset = priv->dp_reg_base[phytium_dp->port];
fifo_value = phytium_readl_reg(priv, group_offset, PHYTIUM_DP_DATA_CONTROL);
if (fifo_value != PHYTIUM_DP_DEFAULT_FIFO_VALUE) {
pr_info("fifo value changed,no hsync change\n");
return;
}


DRM_DEBUG_KMS("before modify hdisplay:%d,h_start:%d,h_end:%d,h_total:%d\n",
temp_mode.crtc_hdisplay, temp_mode.crtc_hsync_start,
temp_mode.crtc_hsync_end, temp_mode.crtc_htotal);


phytium_crtc = to_phytium_crtc(crtc);
phys_pipe = phytium_crtc->phys_pipe;
group_offset = priv->dc_reg_base[phys_pipe];
back_porch = temp_mode.crtc_htotal - temp_mode.crtc_hsync_end;
lines_add = phytium_dp->link_lane_count * HSYNC_LANE_COUNT_MULTI -
(temp_mode.crtc_hsync_end - temp_mode.crtc_hsync_start);

if (lines_add > 0) {
if (lines_add < back_porch) {
temp_mode.crtc_hsync_end += lines_add;
} else {
temp_mode.crtc_hsync_end += (back_porch - HSYNC_MIN_ADJ_OFFSET);
temp_mode.crtc_hsync_start -=
(lines_add - back_porch + HSYNC_MIN_ADJ_OFFSET);

if (temp_mode.crtc_hsync_start < temp_mode.crtc_hdisplay)
temp_mode.crtc_hsync_start =
temp_mode.crtc_hdisplay + HSYNC_MIN_ADJ_OFFSET;
}
} else {
if ((temp_mode.crtc_hsync_end + lines_add) > temp_mode.crtc_hsync_start) {
temp_mode.crtc_hsync_end += lines_add;
} else {
if ((temp_mode.crtc_hsync_end + lines_add) > temp_mode.crtc_hdisplay)
temp_mode.crtc_hsync_start = temp_mode.crtc_hsync_end + lines_add;
else
temp_mode.crtc_hsync_start =
temp_mode.crtc_hdisplay + HSYNC_MIN_ADJ_OFFSET;
temp_mode.crtc_hsync_end =
temp_mode.crtc_hsync_start + HSYNC_MIN_ADJ_OFFSET;
}
}

config = ((temp_mode.crtc_hsync_start & HSYNC_START_MASK) << HSYNC_START_SHIFT)
| ((temp_mode.crtc_hsync_end & HSYNC_END_MASK) << HSYNC_END_SHIFT)
| HSYNC_PULSE_ENABLED;
config |= (temp_mode.flags & DRM_MODE_FLAG_PHSYNC) ? 0 : HSYNC_NEGATIVE;
phytium_writel_reg(priv, config, group_offset, PHYTIUM_DC_HSYNC);

DRM_DEBUG_KMS("after modify hdisplay:%d,h_start:%d,h_end:%d,h_total:%d\n",
temp_mode.crtc_hdisplay, temp_mode.crtc_hsync_start,
temp_mode.crtc_hsync_end, temp_mode.crtc_htotal);

}

static void phytium_encoder_enable(struct drm_encoder *encoder)
{
struct phytium_dp_device *phytium_dp = encoder_to_dp_device(encoder);
Expand All @@ -2198,6 +2329,9 @@ static void phytium_encoder_enable(struct drm_encoder *encoder)
mdelay(2);
}

if (!phytium_dp->is_edp)
phytium_dp_modify_dc_hsync_time(phytium_dp);

phytium_dp_hw_config_video(phytium_dp);
if (ret == 0) {
phytium_dp_hw_enable_video(phytium_dp);
Expand Down Expand Up @@ -2247,12 +2381,6 @@ phytium_encoder_mode_valid(struct drm_encoder *encoder, const struct drm_display
(phytium_dp->native_mode.vtotal == mode->vtotal))
return MODE_OK;

if ((mode->hdisplay == 1600) && (mode->vdisplay == 900))
return MODE_BAD_HVALUE;

if ((mode->hdisplay == 1024) && (mode->clock > 78000))
return MODE_BAD_HVALUE;

if ((mode->hdisplay < 640) || (mode->vdisplay < 480))
return MODE_BAD_HVALUE;

Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/phytium/phytium_dp.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ struct phytium_dp_device {
uint32_t trigger_train_fail;

unsigned char train_set[4];
struct edid *detect_edid;
struct edid *edp_edid;
bool has_audio;
bool fast_train_support;
Expand Down Expand Up @@ -145,6 +146,9 @@ enum phytium_dpcd_phy_tp {
#define connector_to_dp_device(x) container_of(x, struct phytium_dp_device, connector)
#define panel_to_dp_device(x) container_of(x, struct phytium_dp_device, panel)
#define train_retry_to_dp_device(x) container_of(x, struct phytium_dp_device, train_retry_work)
#define HSYNC_LANE_COUNT_MULTI 30
#define HSYNC_MIN_ADJ_OFFSET 1

void phytium_phy_writel(struct phytium_dp_device *phytium_dp, uint32_t address, uint32_t data);
uint32_t phytium_phy_readl(struct phytium_dp_device *phytium_dp, uint32_t address);

Expand Down
6 changes: 4 additions & 2 deletions drivers/gpu/drm/phytium/phytium_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ int phytium_memory_pool_alloc(struct phytium_display_private *priv, void **pvadd

void phytium_memory_pool_free(struct phytium_display_private *priv, void *vaddr, uint64_t size)
{
gen_pool_free(priv->memory_pool, (unsigned long)vaddr, size);
if (priv->memory_pool)
gen_pool_free(priv->memory_pool, (unsigned long)vaddr, size);
}

int phytium_memory_pool_init(struct device *dev, struct phytium_display_private *priv)
Expand Down Expand Up @@ -69,7 +70,8 @@ int phytium_memory_pool_init(struct device *dev, struct phytium_display_private

void phytium_memory_pool_fini(struct device *dev, struct phytium_display_private *priv)
{
gen_pool_destroy(priv->memory_pool);
if (priv->memory_pool)
gen_pool_destroy(priv->memory_pool);
}

struct sg_table *
Expand Down
17 changes: 9 additions & 8 deletions drivers/gpu/drm/phytium/phytium_pci.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,13 +327,22 @@ static int phytium_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
return -1;
}

static void phytium_pci_shutdown(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct phytium_display_private *priv = dev->dev_private;

priv->display_shutdown(dev);
}

static void phytium_pci_remove(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct phytium_display_private *priv = dev->dev_private;

phytium_dp_hpd_irq_setup(dev, false);
cancel_work_sync(&priv->hotplug_work);
phytium_pci_shutdown(pdev);
drm_dev_unregister(dev);
phytium_pci_vram_fini(pdev, priv);
phytium_pci_private_fini(pdev, priv);
Expand All @@ -344,14 +353,6 @@ static void phytium_pci_remove(struct pci_dev *pdev)
drm_dev_put(dev);
}

static void phytium_pci_shutdown(struct pci_dev *pdev)
{
struct drm_device *dev = pci_get_drvdata(pdev);
struct phytium_display_private *priv = dev->dev_private;

priv->display_shutdown(dev);
}

static int phytium_pci_pm_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
Expand Down
17 changes: 9 additions & 8 deletions drivers/gpu/drm/phytium/phytium_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -290,13 +290,22 @@ static int phytium_platform_probe(struct platform_device *pdev)
return -1;
}

static void phytium_platform_shutdown(struct platform_device *pdev)
{
struct drm_device *dev = dev_get_drvdata(&pdev->dev);
struct phytium_display_private *priv = dev->dev_private;

priv->display_shutdown(dev);
}

static int phytium_platform_remove(struct platform_device *pdev)
{
struct drm_device *dev = dev_get_drvdata(&pdev->dev);
struct phytium_display_private *priv = dev->dev_private;

phytium_dp_hpd_irq_setup(dev, false);
cancel_work_sync(&priv->hotplug_work);
phytium_platform_shutdown(pdev);
drm_dev_unregister(dev);
phytium_platform_private_fini(pdev);
dev_set_drvdata(&pdev->dev, NULL);
Expand All @@ -305,14 +314,6 @@ static int phytium_platform_remove(struct platform_device *pdev)
return 0;
}

static void phytium_platform_shutdown(struct platform_device *pdev)
{
struct drm_device *dev = dev_get_drvdata(&pdev->dev);
struct phytium_display_private *priv = dev->dev_private;

priv->display_shutdown(dev);
}

static int phytium_platform_pm_suspend(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/phytium/phytium_reg.h
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@
#define SCRAMBLER_RESET BIT(0)
#define PHYTIUM_DP_SOURCE_CONTROL_STATUS 0x00C4
#define PHYTIUM_DP_DATA_CONTROL 0x00C8
#define PHYTIUM_DP_DEFAULT_FIFO_VALUE 0x20042004
#define PHYTIUM_DP_CORE_CAPABILITY 0x00F8
#define PHYTIUM_DP_CORE_ID 0x00FC
#define PHYTIUM_DP_AUX_COMMAND 0x0100
Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/phytium/px210_dp.c
Original file line number Diff line number Diff line change
Expand Up @@ -896,6 +896,9 @@ int px210_dp_hw_reset(struct phytium_dp_device *phytium_dp)

uint8_t px210_dp_hw_get_source_lane_count(struct phytium_dp_device *phytium_dp)
{
if (source_max_lane_count != 4)
return source_max_lane_count;

return px210_dp_source_lane_count[phytium_dp->port];
}

Expand Down
Loading