diff options
author | Jon Mayo <jmayo@nvidia.com> | 2012-01-11 17:59:55 -0500 |
---|---|---|
committer | Dan Willemsen <dwillemsen@nvidia.com> | 2015-03-18 15:02:02 -0400 |
commit | 5374c03a6c5b5ee5cfe7dfba08c02e91391b653e (patch) | |
tree | 724fc4aff0f4fcb5ee2ae9d6d628bd408f7ae750 /drivers/video | |
parent | 3b1ddb6ae7d6bfa8f7a917873298c31ff03a4c38 (diff) |
video: tegra: dc: 1-shot bandwidth calculation
In one-shot mode(DSI) report emc rate as disabled to reduce bandwidth in
this idle state. Use this same tegra_dc_clear_bandwidth() function to handle
display disable for all types of displays.
Bug 914917
Change-Id: I84ca1341d71999b3558f9dadb103b258a1a6ab6f
Signed-off-by: Jon Mayo <jmayo@nvidia.com>
Reviewed-on: http://git-master/r/74652
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Kevin Huang (Eng-SW) <kevinh@nvidia.com>
Tested-by: Xin Xie <xxie@nvidia.com>
Reviewed-on: http://git-master/r/75536
Reviewed-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Tested-by: Rohan Somvanshi <rsomvanshi@nvidia.com>
Rebase-Id: Rf8b841c11fa8bf67ed3685b671edb221318e3281
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 30 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc_priv.h | 1 |
2 files changed, 25 insertions, 6 deletions
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index 73357ab81..73320b38c 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c | |||
@@ -973,11 +973,21 @@ unsigned long tegra_dc_get_bandwidth(struct tegra_dc_win *windows[], int n) | |||
973 | return tegra_dc_find_max_bandwidth(windows, n); | 973 | return tegra_dc_find_max_bandwidth(windows, n); |
974 | } | 974 | } |
975 | 975 | ||
976 | /* to save power, call when display memory clients would be idle */ | ||
977 | static void tegra_dc_clear_bandwidth(struct tegra_dc *dc) | ||
978 | { | ||
979 | if (dc->emc_clk_rate) | ||
980 | clk_disable(dc->emc_clk); | ||
981 | dc->emc_clk_rate = 0; | ||
982 | } | ||
983 | |||
976 | static void tegra_dc_program_bandwidth(struct tegra_dc *dc) | 984 | static void tegra_dc_program_bandwidth(struct tegra_dc *dc) |
977 | { | 985 | { |
978 | unsigned i; | 986 | unsigned i; |
979 | 987 | ||
980 | if (dc->emc_clk_rate != dc->new_emc_clk_rate) { | 988 | if (dc->emc_clk_rate != dc->new_emc_clk_rate) { |
989 | if (!dc->emc_clk_rate) /* going from 0 to non-zero */ | ||
990 | clk_enable(dc->emc_clk); | ||
981 | dc->emc_clk_rate = dc->new_emc_clk_rate; | 991 | dc->emc_clk_rate = dc->new_emc_clk_rate; |
982 | clk_set_rate(dc->emc_clk, dc->emc_clk_rate); | 992 | clk_set_rate(dc->emc_clk, dc->emc_clk_rate); |
983 | } | 993 | } |
@@ -1249,6 +1259,9 @@ int tegra_dc_update_windows(struct tegra_dc_win *windows[], int n) | |||
1249 | if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) | 1259 | if (dc->out->flags & TEGRA_DC_OUT_ONE_SHOT_MODE) |
1250 | tegra_dc_writel(dc, NC_HOST_TRIG, DC_CMD_STATE_CONTROL); | 1260 | tegra_dc_writel(dc, NC_HOST_TRIG, DC_CMD_STATE_CONTROL); |
1251 | 1261 | ||
1262 | /* update EMC clock if calculated bandwidth has changed */ | ||
1263 | tegra_dc_program_bandwidth(dc); | ||
1264 | |||
1252 | mutex_unlock(&dc->lock); | 1265 | mutex_unlock(&dc->lock); |
1253 | 1266 | ||
1254 | return 0; | 1267 | return 0; |
@@ -1922,9 +1935,6 @@ static void tegra_dc_vblank(struct work_struct *work) | |||
1922 | 1935 | ||
1923 | mutex_lock(&dc->lock); | 1936 | mutex_lock(&dc->lock); |
1924 | 1937 | ||
1925 | /* update EMC clock if calculated bandwidth has changed */ | ||
1926 | tegra_dc_program_bandwidth(dc); | ||
1927 | |||
1928 | /* Update the SD brightness */ | 1938 | /* Update the SD brightness */ |
1929 | if (dc->enabled && dc->out->sd_settings) | 1939 | if (dc->enabled && dc->out->sd_settings) |
1930 | nvsd_updated = nvsd_update_brightness(dc); | 1940 | nvsd_updated = nvsd_update_brightness(dc); |
@@ -1942,6 +1952,13 @@ static void tegra_dc_vblank(struct work_struct *work) | |||
1942 | } | 1952 | } |
1943 | } | 1953 | } |
1944 | 1954 | ||
1955 | static void tegra_dc_one_shot_worker(struct work_struct *work) | ||
1956 | { | ||
1957 | struct tegra_dc *dc = container_of(work, struct tegra_dc, one_shot_work); | ||
1958 | /* memory client has gone idle */ | ||
1959 | tegra_dc_clear_bandwidth(dc); | ||
1960 | } | ||
1961 | |||
1945 | /* return an arbitrarily large number if count overflow occurs. | 1962 | /* return an arbitrarily large number if count overflow occurs. |
1946 | * make it a nice base-10 number to show up in stats output */ | 1963 | * make it a nice base-10 number to show up in stats output */ |
1947 | static u64 tegra_dc_underflow_count(struct tegra_dc *dc, unsigned reg) | 1964 | static u64 tegra_dc_underflow_count(struct tegra_dc *dc, unsigned reg) |
@@ -2038,6 +2055,8 @@ static void tegra_dc_one_shot_irq(struct tegra_dc *dc, unsigned long status) | |||
2038 | } | 2055 | } |
2039 | 2056 | ||
2040 | if (status & FRAME_END_INT) { | 2057 | if (status & FRAME_END_INT) { |
2058 | schedule_work(&dc->one_shot_work); | ||
2059 | |||
2041 | /* Mark the frame_end as complete. */ | 2060 | /* Mark the frame_end as complete. */ |
2042 | if (!completion_done(&dc->frame_end_complete)) | 2061 | if (!completion_done(&dc->frame_end_complete)) |
2043 | complete(&dc->frame_end_complete); | 2062 | complete(&dc->frame_end_complete); |
@@ -2288,7 +2307,6 @@ static bool _tegra_dc_controller_enable(struct tegra_dc *dc) | |||
2288 | 2307 | ||
2289 | tegra_dc_setup_clk(dc, dc->clk); | 2308 | tegra_dc_setup_clk(dc, dc->clk); |
2290 | clk_enable(dc->clk); | 2309 | clk_enable(dc->clk); |
2291 | clk_enable(dc->emc_clk); | ||
2292 | 2310 | ||
2293 | /* do not accept interrupts during initialization */ | 2311 | /* do not accept interrupts during initialization */ |
2294 | tegra_dc_writel(dc, 0, DC_CMD_INT_ENABLE); | 2312 | tegra_dc_writel(dc, 0, DC_CMD_INT_ENABLE); |
@@ -2320,7 +2338,6 @@ static bool _tegra_dc_controller_reset_enable(struct tegra_dc *dc) | |||
2320 | 2338 | ||
2321 | tegra_dc_setup_clk(dc, dc->clk); | 2339 | tegra_dc_setup_clk(dc, dc->clk); |
2322 | clk_enable(dc->clk); | 2340 | clk_enable(dc->clk); |
2323 | clk_enable(dc->emc_clk); | ||
2324 | 2341 | ||
2325 | if (dc->ndev->id == 0 && tegra_dcs[1] != NULL) { | 2342 | if (dc->ndev->id == 0 && tegra_dcs[1] != NULL) { |
2326 | mutex_lock(&tegra_dcs[1]->lock); | 2343 | mutex_lock(&tegra_dcs[1]->lock); |
@@ -2397,7 +2414,7 @@ static void _tegra_dc_controller_disable(struct tegra_dc *dc) | |||
2397 | if (dc->out_ops && dc->out_ops->disable) | 2414 | if (dc->out_ops && dc->out_ops->disable) |
2398 | dc->out_ops->disable(dc); | 2415 | dc->out_ops->disable(dc); |
2399 | 2416 | ||
2400 | clk_disable(dc->emc_clk); | 2417 | tegra_dc_clear_bandwidth(dc); |
2401 | clk_disable(dc->clk); | 2418 | clk_disable(dc->clk); |
2402 | tegra_dvfs_set_rate(dc->clk, 0); | 2419 | tegra_dvfs_set_rate(dc->clk, 0); |
2403 | 2420 | ||
@@ -2653,6 +2670,7 @@ static int tegra_dc_probe(struct nvhost_device *ndev) | |||
2653 | #endif | 2670 | #endif |
2654 | INIT_WORK(&dc->vblank_work, tegra_dc_vblank); | 2671 | INIT_WORK(&dc->vblank_work, tegra_dc_vblank); |
2655 | INIT_DELAYED_WORK(&dc->underflow_work, tegra_dc_underflow_worker); | 2672 | INIT_DELAYED_WORK(&dc->underflow_work, tegra_dc_underflow_worker); |
2673 | INIT_WORK(&dc->one_shot_work, tegra_dc_one_shot_worker); | ||
2656 | 2674 | ||
2657 | tegra_dc_init_lut_defaults(&dc->fb_lut); | 2675 | tegra_dc_init_lut_defaults(&dc->fb_lut); |
2658 | 2676 | ||
diff --git a/drivers/video/tegra/dc/dc_priv.h b/drivers/video/tegra/dc/dc_priv.h index 2245b4eb4..989fa1b5f 100644 --- a/drivers/video/tegra/dc/dc_priv.h +++ b/drivers/video/tegra/dc/dc_priv.h | |||
@@ -133,6 +133,7 @@ struct tegra_dc { | |||
133 | #endif | 133 | #endif |
134 | struct tegra_dc_lut fb_lut; | 134 | struct tegra_dc_lut fb_lut; |
135 | struct delayed_work underflow_work; | 135 | struct delayed_work underflow_work; |
136 | struct work_struct one_shot_work; | ||
136 | }; | 137 | }; |
137 | 138 | ||
138 | static inline void tegra_dc_io_start(struct tegra_dc *dc) | 139 | static inline void tegra_dc_io_start(struct tegra_dc *dc) |