diff options
author | Pekka Pessi <ppessi@nvidia.com> | 2017-07-09 14:13:55 -0400 |
---|---|---|
committer | mobile promotions <svcmobile_promotions@nvidia.com> | 2017-07-12 16:24:50 -0400 |
commit | 5a48f5db2a18a5bae491ff98b1fc0c23fe3780b7 (patch) | |
tree | 3f38372e4c8e49cd2a842082ad86861307acefda /drivers/media | |
parent | 9547278fccaefa009356207312dd368d607cae6c (diff) |
media: tegra: camera: slvs: variable syncgen clock
While the syncgen clock is constant in silicon, the simulation can
use much slower clock speeds. Make syngen clock as a variable with
default value of 72 MHz on VDK or linsim.
Jira CAMC-382
Change-Id: Id2f8ebc4cffc440297f930e7bdafedce1cc15910
Signed-off-by: Pekka Pessi <ppessi@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/1515907
GVS: Gerrit_Virtual_Submit
Reviewed-by: Aki Niemi <aniemi@nvidia.com>
Reviewed-by: Jihoon Bang <jbang@nvidia.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/platform/tegra/camera/slvs/slvs.c | 37 |
1 files changed, 30 insertions, 7 deletions
diff --git a/drivers/media/platform/tegra/camera/slvs/slvs.c b/drivers/media/platform/tegra/camera/slvs/slvs.c index a81c46bf9..5b7b7d98f 100644 --- a/drivers/media/platform/tegra/camera/slvs/slvs.c +++ b/drivers/media/platform/tegra/camera/slvs/slvs.c | |||
@@ -25,13 +25,15 @@ | |||
25 | #include <media/mc_common.h> | 25 | #include <media/mc_common.h> |
26 | #include <media/slvs.h> | 26 | #include <media/slvs.h> |
27 | 27 | ||
28 | #include <soc/tegra/chip-id.h> | ||
29 | |||
28 | #include "dev.h" | 30 | #include "dev.h" |
29 | #include "linux/nvhost.h" | 31 | #include "linux/nvhost.h" |
30 | #include <linux/version.h> | 32 | #include <linux/version.h> |
31 | 33 | ||
32 | #define SLVSEC_NUM_LANES 8 | 34 | #define SLVSEC_NUM_LANES 8 |
33 | 35 | ||
34 | #define SYCNGEN_CLOCK U64_C(408000) | 36 | #define SYNCGEN_CLOCK U32_C(408000) |
35 | #define XSYNC_WIDTH 4 | 37 | #define XSYNC_WIDTH 4 |
36 | #define VI_NUM_VGP 6 | 38 | #define VI_NUM_VGP 6 |
37 | #define VI_NUM_SYNCGEN 3 | 39 | #define VI_NUM_SYNCGEN 3 |
@@ -107,6 +109,8 @@ struct tegra_mc_slvs { | |||
107 | void __iomem *slvs_base; | 109 | void __iomem *slvs_base; |
108 | void __iomem *vi_base; | 110 | void __iomem *vi_base; |
109 | 111 | ||
112 | u32 syncgen_clock; | ||
113 | |||
110 | atomic_t power_ref; | 114 | atomic_t power_ref; |
111 | atomic_t sensor_active; | 115 | atomic_t sensor_active; |
112 | 116 | ||
@@ -386,9 +390,11 @@ static inline void slvs_vi_syncgen_stop(struct tegra_mc_slvs *slvs, | |||
386 | } | 390 | } |
387 | 391 | ||
388 | static int slvs_get_syncgen_config( | 392 | static int slvs_get_syncgen_config( |
393 | struct tegra_mc_slvs *slvs, | ||
389 | const struct camera_common_framesync *fs, | 394 | const struct camera_common_framesync *fs, |
390 | struct slvsec_syncgen_config *cfg) | 395 | struct slvsec_syncgen_config *cfg) |
391 | { | 396 | { |
397 | u64 syncgen_clock = slvs->syncgen_clock; | ||
392 | /* HS per 1000 second. */ | 398 | /* HS per 1000 second. */ |
393 | u64 hs_per_1000sec = (u64)fs->xvs * fs->fps; | 399 | u64 hs_per_1000sec = (u64)fs->xvs * fs->fps; |
394 | u64 xhs; | 400 | u64 xhs; |
@@ -398,7 +404,7 @@ static int slvs_get_syncgen_config( | |||
398 | if (hs_per_1000sec == 0) | 404 | if (hs_per_1000sec == 0) |
399 | return -EINVAL; | 405 | return -EINVAL; |
400 | 406 | ||
401 | xhs = ((10 * 1000 * SYCNGEN_CLOCK) << 32) / hs_per_1000sec * 100; | 407 | xhs = ((10 * 1000 * syncgen_clock) << 32) / hs_per_1000sec * 100; |
402 | 408 | ||
403 | for (frac = 0; (xhs >> (frac + 32)) != 0; frac++) | 409 | for (frac = 0; (xhs >> (frac + 32)) != 0; frac++) |
404 | ; | 410 | ; |
@@ -407,7 +413,9 @@ static int slvs_get_syncgen_config( | |||
407 | cfg->hclk_div_fmt = 31 - frac; | 413 | cfg->hclk_div_fmt = 31 - frac; |
408 | 414 | ||
409 | /* At least XSYNC_WIDTH iclk cycles */ | 415 | /* At least XSYNC_WIDTH iclk cycles */ |
410 | width = (XSYNC_WIDTH * SYCNGEN_CLOCK + fs->inck - 1) / fs->inck; | 416 | width = (XSYNC_WIDTH * syncgen_clock + fs->inck - 1) / fs->inck; |
417 | if (width < XSYNC_WIDTH) | ||
418 | width = XSYNC_WIDTH; | ||
411 | 419 | ||
412 | cfg->xhs_width = width; | 420 | cfg->xhs_width = width; |
413 | cfg->xvs_width = width; | 421 | cfg->xvs_width = width; |
@@ -426,7 +434,8 @@ static int tegra_slvs_syncgen_start(struct tegra_slvs_stream *stream) | |||
426 | struct slvsec_syncgen_config config; | 434 | struct slvsec_syncgen_config config; |
427 | int err; | 435 | int err; |
428 | 436 | ||
429 | err = slvs_get_syncgen_config(&stream->framesync, &config); | 437 | err = slvs_get_syncgen_config(slvs, |
438 | &stream->framesync, &config); | ||
430 | if (err) | 439 | if (err) |
431 | return err; | 440 | return err; |
432 | 441 | ||
@@ -474,12 +483,14 @@ static void fractional_binary(char buffer[35], u32 value, u32 fraction) | |||
474 | static int slvs_debugfs_syncgen_config_read(struct seq_file *s, void *data) | 483 | static int slvs_debugfs_syncgen_config_read(struct seq_file *s, void *data) |
475 | { | 484 | { |
476 | struct tegra_slvs_stream *stream = s->private; | 485 | struct tegra_slvs_stream *stream = s->private; |
486 | struct tegra_mc_slvs *slvs = stream->slvs; | ||
487 | u64 syncgen_clock = slvs->syncgen_clock; | ||
477 | int err; | 488 | int err; |
478 | struct slvsec_syncgen_config config; | 489 | struct slvsec_syncgen_config config; |
479 | char buffer[35]; | 490 | char buffer[35]; |
480 | u64 framerate; | 491 | u64 framerate; |
481 | 492 | ||
482 | err = slvs_get_syncgen_config(&stream->framesync, &config); | 493 | err = slvs_get_syncgen_config(slvs, &stream->framesync, &config); |
483 | if (err < 0) | 494 | if (err < 0) |
484 | return err; | 495 | return err; |
485 | 496 | ||
@@ -488,7 +499,7 @@ static int slvs_debugfs_syncgen_config_read(struct seq_file *s, void *data) | |||
488 | 499 | ||
489 | fractional_binary(buffer, config.hclk_div, config.hclk_div_fmt); | 500 | fractional_binary(buffer, config.hclk_div, config.hclk_div_fmt); |
490 | 501 | ||
491 | framerate = (1000 * SYCNGEN_CLOCK) << 32; | 502 | framerate = (1000 * syncgen_clock) << 32; |
492 | framerate /= config.hclk_div; | 503 | framerate /= config.hclk_div; |
493 | framerate /= config.xvs_interval; | 504 | framerate /= config.xvs_interval; |
494 | /* Multiply framerate by 2000 followed by right shift by 32 */ | 505 | /* Multiply framerate by 2000 followed by right shift by 32 */ |
@@ -498,7 +509,7 @@ static int slvs_debugfs_syncgen_config_read(struct seq_file *s, void *data) | |||
498 | else | 509 | else |
499 | framerate >>= (32 - 3) - config.hclk_div_fmt; | 510 | framerate >>= (32 - 3) - config.hclk_div_fmt; |
500 | 511 | ||
501 | seq_printf(s, "clk = %llu\n", 1000ULL * SYCNGEN_CLOCK); | 512 | seq_printf(s, "clk = %llu\n", 1000ULL * syncgen_clock); |
502 | seq_printf(s, "hclk_div = %u >> %u (%s)\n", | 513 | seq_printf(s, "hclk_div = %u >> %u (%s)\n", |
503 | config.hclk_div, config.hclk_div_fmt, buffer); | 514 | config.hclk_div, config.hclk_div_fmt, buffer); |
504 | seq_printf(s, "xvs = %u\n", config.xvs_interval); | 515 | seq_printf(s, "xvs = %u\n", config.xvs_interval); |
@@ -601,6 +612,9 @@ static void tegra_slvs_init_debugfs(struct tegra_mc_slvs *slvs) | |||
601 | char name[32]; | 612 | char name[32]; |
602 | struct dentry *dir; | 613 | struct dentry *dir; |
603 | 614 | ||
615 | debugfs_create_u32("syncgen-clock", S_IRUGO | S_IWUSR, info->debugfs, | ||
616 | &slvs->syncgen_clock); | ||
617 | |||
604 | for (i = 0; i < slvs->num_streams; i++) { | 618 | for (i = 0; i < slvs->num_streams; i++) { |
605 | snprintf(name, sizeof(name), "mc@%d", i); | 619 | snprintf(name, sizeof(name), "mc@%d", i); |
606 | dir = debugfs_create_dir(name, info->debugfs); | 620 | dir = debugfs_create_dir(name, info->debugfs); |
@@ -1009,6 +1023,9 @@ static int tegra_slvs_parse_dt(struct tegra_mc_slvs *slvs) | |||
1009 | struct tegra_slvs_stream *stream; | 1023 | struct tegra_slvs_stream *stream; |
1010 | int i; | 1024 | int i; |
1011 | 1025 | ||
1026 | (void)of_property_read_u32(node, "nvidia,syncgen-clock", | ||
1027 | &slvs->syncgen_clock); | ||
1028 | |||
1012 | if (num_streams <= 0) { | 1029 | if (num_streams <= 0) { |
1013 | dev_info(slvs->dev, "no streams defined"); | 1030 | dev_info(slvs->dev, "no streams defined"); |
1014 | return -ENODEV; | 1031 | return -ENODEV; |
@@ -1076,6 +1093,12 @@ struct tegra_mc_slvs *tegra_slvs_media_controller_init( | |||
1076 | slvs->slvs_base = pdata->aperture[0]; | 1093 | slvs->slvs_base = pdata->aperture[0]; |
1077 | slvs->vi_base = pdata->aperture[1]; | 1094 | slvs->vi_base = pdata->aperture[1]; |
1078 | 1095 | ||
1096 | slvs->syncgen_clock = SYNCGEN_CLOCK; | ||
1097 | |||
1098 | if (tegra_platform_is_linsim() || tegra_platform_is_vdk()) { | ||
1099 | slvs->syncgen_clock = 72000; /* 72 MHz */ | ||
1100 | } | ||
1101 | |||
1079 | atomic_set(&slvs->power_ref, 0); | 1102 | atomic_set(&slvs->power_ref, 0); |
1080 | 1103 | ||
1081 | err = tegra_slvs_parse_dt(slvs); | 1104 | err = tegra_slvs_parse_dt(slvs); |