Skip to content

Commit

Permalink
Merge pull request torvalds#100 from 96boards/working-syspll-get-from…
Browse files Browse the repository at this point in the history
…-registers-v3

Working syspll get from registers v3
  • Loading branch information
docularxu committed Jul 23, 2015
2 parents f10632d + 38f1300 commit 9212a52
Show file tree
Hide file tree
Showing 21 changed files with 2,593 additions and 1,426 deletions.
3 changes: 3 additions & 0 deletions arch/arm64/boot/dts/hi6220.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,9 @@
pd-gpio = <&gpio0 4 0>;
adi,input-depth = <8>;
adi,input-colorspace = "rgb";
adi,input-clock = "1x";
adi,clock-delay = <0>;
adi,embedded-sync;
};
};

Expand Down
3 changes: 2 additions & 1 deletion arch/arm64/configs/defconfig
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,7 @@ CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_FW_LOADER_USER_HELPER_FALLBACK=y
CONFIG_DMA_CMA=y
CONFIG_CMA_SIZE_MBYTES=64
CONFIG_CONNECTOR=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
Expand Down Expand Up @@ -276,7 +277,7 @@ CONFIG_MALI_SHARED_INTERRUPTS=y
CONFIG_MALI_DT=y
CONFIG_MALI_PLAT_SPECIFIC_DT=y
CONFIG_DRM=y
CONFIG_DRM_I2C_ADV7533=y
CONFIG_DRM_I2C_ADV7511=y
CONFIG_DRM_HISI=y
CONFIG_ION_HISI=y
CONFIG_FB_ARMCLCD=y
Expand Down
43 changes: 38 additions & 5 deletions drivers/clk/hisilicon/clk-hi6220.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
* published by the Free Software Foundation.
*/

#include <linux/kernel.h>
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/clk.h>

#include <dt-bindings/clock/hi6220-clock.h>

Expand All @@ -35,9 +35,9 @@ static struct hisi_fixed_rate_clock hi6220_fixed_rate_clks[] __initdata = {
{ HI6220_PLL_BBP, "bbppll0", NULL, CLK_IS_ROOT, 245760000, },
{ HI6220_PLL_GPU, "gpupll", NULL, CLK_IS_ROOT, 1000000000,},
{ HI6220_PLL1_DDR, "ddrpll1", NULL, CLK_IS_ROOT, 1066000000,},
{ HI6220_PLL_SYS, "syspll", NULL, CLK_IS_ROOT, 1200000000,},
{ HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, CLK_IS_ROOT, 1200000000,},
{ HI6220_DDR_SRC, "ddr_sel_src", NULL, CLK_IS_ROOT, 1200000000,},
{ HI6220_PLL_SYS, "syspll", NULL, CLK_IS_ROOT, 1190494208,},
{ HI6220_PLL_SYS_MEDIA, "media_syspll", NULL, CLK_IS_ROOT, 1190494208,},
{ HI6220_DDR_SRC, "ddr_sel_src", NULL, CLK_IS_ROOT, 1190494208,},
{ HI6220_PLL_MEDIA, "media_pll", NULL, CLK_IS_ROOT, 1440000000,},
{ HI6220_PLL_DDR, "ddrpll0", NULL, CLK_IS_ROOT, 1600000000,},
};
Expand Down Expand Up @@ -73,14 +73,47 @@ static struct hisi_gate_clock hi6220_separated_gate_clks_ao[] __initdata = {
{ HI6220_RTC1_PCLK, "rtc1_pclk", "clk_tcxo", CLK_SET_RATE_PARENT|CLK_IGNORE_UNUSED, 0x630, 26, 0, },
};

#define SOC_PERI_SCTRL_BASE_ADDR 0xF7030000 /* peri ctrl base addr */
#define SC_PERIPH_CTRL14 0x02C
#define SC_PERIPH_STAT1 0x094

static struct hisi_clock_data *clk_data_ao;

static void __init hi6220_clk_ao_init(struct device_node *np)
{
void __iomem *peri_base;
unsigned int syspll_freq;
int i;

clk_data_ao = hisi_clk_init(np, HI6220_AO_NR_CLKS);
if (!clk_data_ao)
return;

/* SYSPLL is set by bootloader. Read it */
peri_base = ioremap(SOC_PERI_SCTRL_BASE_ADDR, 0x1000);
/* 0x2101 means to calculate clk_sys_pll */
writel(0x2101, peri_base + SC_PERIPH_CTRL14);
/* read back the calculated value */
syspll_freq = readl(peri_base + SC_PERIPH_STAT1);
pr_info("SYSPLL: syspll_freq is read: 0x%x, %d\n", syspll_freq, \
syspll_freq);
if (syspll_freq == 0x00020000 || syspll_freq == 0)
syspll_freq = 1200000000;
pr_info("SYSPLL: set syspll medpll ddrsrc: %d\n", syspll_freq);

for (i = 0; i < ARRAY_SIZE(hi6220_fixed_rate_clks); i++) {
switch (hi6220_fixed_rate_clks[i].id) {
case HI6220_PLL_SYS:
case HI6220_PLL_SYS_MEDIA:
case HI6220_DDR_SRC:
hi6220_fixed_rate_clks[i].fixed_rate = syspll_freq;
pr_info("SYSPLL: modified fix_rate[%d], id=%d, f=%d\n", \
i, hi6220_fixed_rate_clks[i].id, syspll_freq);
default:
break;
}
}

hisi_clk_register_fixed_rate(hi6220_fixed_rate_clks,
ARRAY_SIZE(hi6220_fixed_rate_clks),
clk_data_ao);
Expand Down
11 changes: 11 additions & 0 deletions drivers/gpu/drm/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,17 @@ source "drivers/gpu/drm/i2c/Kconfig"

source "drivers/gpu/drm/bridge/Kconfig"

config DRM_SYSRQ_MODE_HACK
bool "Allow SysRq-g to cycle through modes (1 crtc only)"
depends on DRM
help
Select this option if your mode / timing generation is not so
reliable that you can always show the preferred mode on any
monitor and there are no arrangements on the platform to change
it by hand. You can use AltGr-Sysrq-g to cycle between the
available modes when this is enabled. It only understands one
CRTC.

config DRM_TDFX
tristate "3dfx Banshee/Voodoo3+"
depends on DRM && PCI
Expand Down
79 changes: 79 additions & 0 deletions drivers/gpu/drm/drm_crtc_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,82 @@ drm_crtc_prepare_encoders(struct drm_device *dev)
}
}

#ifdef CONFIG_DRM_SYSRQ_MODE_HACK
static struct drm_mode_set modehack_set;
static void modehack_handler(struct work_struct *work)
{
struct drm_connector *connector = NULL, *connector1;
struct drm_display_mode *mode1, *mode_first = NULL, *mode2 = NULL;
bool next = false;
char *envp[2];

if (!modehack_set.crtc)
return;

drm_modeset_lock_all(modehack_set.crtc->dev);

/* find our connector */
list_for_each_entry(connector1,
&modehack_set.crtc->dev->mode_config.connector_list,
head) {
if (!connector)
connector = connector1;
}
if (!connector) {
pr_err("no connector\n");
goto bail;
}

/* identify our current mode and the "next" */
list_for_each_entry(mode1, &connector->modes, head) {
if (!mode_first)
mode_first = mode1;
if (next) {
next = false;
mode2 = mode1;
}
next = drm_mode_equal(&modehack_set.crtc->mode, mode1);
}

/* if next never appeared, loop back to first one */
if (!mode2)
mode2 = mode_first;

pr_err("Trying %dx%d@%d, %dkHz\n", mode2->hdisplay, mode2->vdisplay,
((mode2->clock * 1000) / (mode2->htotal * mode2->vtotal)),
mode2->clock);

modehack_set.mode = mode2;
modehack_set.connectors = &connector;
modehack_set.num_connectors = 1;

drm_helper_connector_dpms(connector, DRM_MODE_DPMS_STANDBY);
drm_crtc_helper_set_config(&modehack_set);
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);

envp[0] = "SOURCE=hotkey";
envp[1] = NULL;
kobject_uevent_env(&connector->kdev->kobj, KOBJ_CHANGE, envp);

bail:
drm_modeset_unlock_all(modehack_set.crtc->dev);
}

static DECLARE_WORK(modehack_work, modehack_handler);

/*
* Alt-Gr SYSRQ g magically calls this
*/
void sysrq_handle_modehack(int key)
{
if (!modehack_set.crtc)
return;

schedule_work(&modehack_work);
}
EXPORT_SYMBOL_GPL(sysrq_handle_modehack);
#endif

/**
* drm_crtc_helper_set_mode - internal helper to set a mode
* @crtc: CRTC to program
Expand Down Expand Up @@ -268,6 +344,9 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
return false;
}

modehack_set.fb = crtc->primary->fb;
modehack_set.crtc = crtc;

saved_mode = crtc->mode;
saved_x = crtc->x;
saved_y = crtc->y;
Expand Down
10 changes: 10 additions & 0 deletions drivers/gpu/drm/drm_fb_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -1262,6 +1262,16 @@ struct drm_display_mode *drm_pick_cmdline_mode(struct drm_fb_helper_connector *f
}

create_mode:
/*
* Synthetic mode timing is very unlikely to work on HDMI. Instead
* if there is a fallback mode, give up on trying to guess the forced
* mode timing and just let the forced mode deal with it.
*/
if (fb_helper_conn->connector->funcs->fallback_mode) {
pr_err("%s: preferring fallback mode\n", __func__);
return NULL;
}

mode = drm_mode_create_from_cmdline_mode(fb_helper_conn->connector->dev,
cmdline_mode);
list_add(&mode->head, &fb_helper_conn->connector->modes);
Expand Down
21 changes: 15 additions & 6 deletions drivers/gpu/drm/drm_probe_helper.c
Original file line number Diff line number Diff line change
Expand Up @@ -155,11 +155,15 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
count = (*connector_funcs->get_modes)(connector);
}

if (count == 0 && connector->status == connector_status_connected)
if (count == 0 && connector->status == connector_status_connected &&
!connector->funcs->fallback_mode)
count = drm_add_modes_noedid(connector, 1024, 768);
count += drm_helper_probe_add_cmdline_mode(connector);
if (count == 0)
goto prune;

if (count || !connector->funcs->fallback_mode) {
count += drm_helper_probe_add_cmdline_mode(connector);
if (count == 0)
goto prune;
}

drm_mode_connector_list_update(connector, merge_type_bits);

Expand All @@ -183,8 +187,13 @@ static int drm_helper_probe_single_connector_modes_merge_bits(struct drm_connect
prune:
drm_mode_prune_invalid(dev, &connector->modes, verbose_prune);

if (list_empty(&connector->modes))
return 0;
if (list_empty(&connector->modes)) {
if (!connector->funcs->fallback_mode)
return 0;
if (connector->funcs->fallback_mode(connector))
return 0;
count = 1;
}

list_for_each_entry(mode, &connector->modes, head)
mode->vrefresh = drm_mode_vrefresh(mode);
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/hisilicon/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ config DRM_HISI
select DRM_GEM_CMA_HELPER
select DRM_PANEL
select DRM_MIPI_DSI
select DRM_SYSRQ_MODE_HACK
help
Choose this option if you have a hisilicon terminal chipset.
If M is selected the module will be called hisi-drm.
Expand Down
Loading

0 comments on commit 9212a52

Please sign in to comment.